Compare commits

..

611 Commits

Author SHA1 Message Date
AlexeyZavar c86ea4807a feat: emoji pack author 2024-06-05 04:32:56 +03:00
AlexeyZavar b5c769196a fix: channel badge 2024-06-05 03:36:18 +03:00
Nikhil Singh 6027bad788 fix: add telegram string in keywords (#11)
This will make AyuGram easy to search in linux app menu's and other drun utilities like rofi/dmenu
2024-06-04 04:15:58 +03:00
AlexeyZavar 0b1e6bd1de fix: make it build 2024-06-04 04:11:16 +03:00
AlexeyZavar 01b8602437 Merge tag 'v5.1.2' into dev
# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/boxes/send_files_box.cpp
#	Telegram/SourceFiles/core/version.h
#	Telegram/SourceFiles/data/data_search_controller.cpp
#	Telegram/SourceFiles/dialogs/dialogs_widget.cpp
#	Telegram/SourceFiles/dialogs/dialogs_widget.h
#	Telegram/SourceFiles/history/view/media/history_view_gif.cpp
#	Telegram/SourceFiles/mainwidget.cpp
#	Telegram/lib_ui
2024-06-04 03:29:15 +03:00
AlexeyZavar cc16922673 feat: copy username for channels too
fix: purge useless
2024-06-04 03:21:44 +03:00
John Preston 379a94db42 Version 5.1.2.
- Several bugs fixed including a couple of crashes.
2024-06-04 00:00:12 +04:00
23rd 4f4d216987 Fixed display of button in channel earn section when balance is low. 2024-06-03 23:00:48 +04:00
23rd 6400875d55 Replaced text drawing in menu from phone handler with Text::String. 2024-06-03 23:00:47 +04:00
John Preston 06d0e78b00 Fix a crash in forwarded sender avatars. 2024-06-03 22:59:14 +04:00
John Preston 9043c18725 Don't drop search on non-empty backspace. 2024-06-03 22:27:15 +04:00
Ilya Fedin 88e742927f File descriptor fixes for XDPOpenWithDialog
- Open it with O_CLOEXEC
- Remove unneseccary std::array complication
- Rely on Gio::UnixFDList to close it
2024-06-03 17:49:16 +04:00
Ilya Fedin a6fcc6d51d Rely on media viewer code to close itself before ShowInFolder 2024-06-03 17:49:16 +04:00
John Preston 23a13ab54e Close chats search when selecting a folder. 2024-06-03 17:13:14 +04:00
John Preston e8a929bdbd Fix bottom info display in media. 2024-06-03 15:03:41 +04:00
John Preston eafc01e02b Fix small photo display in wide enough chat.
Fixes #28004.
2024-06-03 14:14:42 +04:00
John Preston f817504d67 Fix formatting drop on zero cursor position. 2024-06-03 13:52:00 +04:00
John Preston f91eb65239 Fix channel reactions editing. 2024-06-03 13:40:04 +04:00
John Preston e978770fbd Fix crash in theme IV opening. 2024-06-03 12:48:11 +04:00
23rd 9c83b8bac5 Fixed emoji display in reply markup button from bar for pinned messages. 2024-06-02 23:11:09 +03:00
23rd 47ce34e987 Added initial support of vcard from media contacts. 2024-06-02 22:06:49 +03:00
John Preston 1656a9c3e2 Fix bot about title display. 2024-06-02 10:55:13 +04:00
John Preston 47e06cf385 Fix dropping invertCaption on reschedule. 2024-06-02 10:55:13 +04:00
John Preston f61f649a7e Add a power saving setting for effects. 2024-06-02 10:55:13 +04:00
John Preston a7bffe7abd Version 5.1.1: Fix misspelled attribute. 2024-06-01 23:58:31 +04:00
John Preston 51b866293f Version 5.1.1.
- Fix caption display on some media.
- Fix collapsed blockquotes rendering.
- Fully close search in chat by "Cancel" click.
- Allow editing caption placement and spoiler in topics.
- Disable effects on forwarded messages and inline results.
2024-06-01 23:40:20 +04:00
John Preston bd20a3cfe4 Fix filtered premium sticker effects selection. 2024-06-01 23:35:04 +04:00
John Preston 86778aa4d9 Fix cancel search glitch with the new search. 2024-06-01 23:26:02 +04:00
John Preston 12eecec501 Disable effects for inline results sending. 2024-06-01 23:21:48 +04:00
John Preston 26345208a9 Fix caption disappearance on album sending. 2024-06-01 23:02:29 +04:00
John Preston ee680ac1f1 Don't try adding effects to forwarded messages. 2024-06-01 22:49:51 +04:00
John Preston bb79a07262 Move SendMenu additional actions to bottom. 2024-06-01 22:43:19 +04:00
John Preston 70fe649743 Hide media viewer on macOS when showing IV. 2024-06-01 22:31:43 +04:00
John Preston 400f0f8785 Empty line between description and ID. 2024-06-01 22:09:01 +04:00
John Preston eac7bf1c48 Show "View as Messages" preview on forum preview. 2024-06-01 22:02:17 +04:00
John Preston f4abe37dff Display peer IDs with delimeters. 2024-06-01 21:53:41 +04:00
John Preston b7f165a259 Fix albums with wide captions. 2024-06-01 21:53:26 +04:00
John Preston c1b95afd88 Fix media spoiler/caption-above edit in topics/scheduled. 2024-06-01 21:17:09 +04:00
John Preston 36766e7546 Fix collapsed blockquotes in the end of the text. 2024-06-01 21:16:31 +04:00
John Preston 59c016e4ce Fix search input not in the end of the query. 2024-06-01 20:39:31 +04:00
John Preston e9e347fa6c Fix crash in stories privacy handling. 2024-06-01 20:34:16 +04:00
23rd 7aef0b0a83 Fixed frame size of video userpic in short info boxes on Retina. 2024-06-01 16:55:01 +03:00
23rd d9572949f6 Replaced confirmation box for proxy links with generic box. 2024-06-01 16:02:59 +03:00
23rd 233e80d22d Fixed display of confirmation box for proxy links in correspond window. 2024-06-01 16:02:59 +03:00
John Preston 5c83858a50 Remove empty space below video without caption. 2024-06-01 10:58:48 +04:00
John Preston c681569349 Fix info display in video with caption above. 2024-06-01 10:53:00 +04:00
John Preston bb43afdd93 Fix search in chat close by "Cancel" link. 2024-06-01 10:52:48 +04:00
John Preston 3ba1941808 Version 5.1: Fix build on macOS. 2024-05-31 23:03:06 +04:00
John Preston 72d1b43453 Version 5.1.
- Send messages with effects.
- Move photo or video captions above the media.
- Chat preview on chat photo long press or Alt+Click.
2024-05-31 21:30:18 +04:00
John Preston 0c1b487956 Fix dragging of non-leader media. 2024-05-31 21:30:18 +04:00
23rd ba611d0f2d Added initial api support of text phone entity in messages. 2024-05-31 18:58:21 +03:00
23rd 50ce847b31 Fixed display of info in media from chat preview. 2024-05-31 19:52:36 +04:00
23rd dd0d88ccd3 Fixed userpic views in headers of forwarded messages with via bots. 2024-05-31 19:52:36 +04:00
John Preston a1049ec7ce Add touchscreen preview to recent / channels. 2024-05-31 19:52:36 +04:00
John Preston 0fffeac8da Fix drag-n-drop forward of selected album. 2024-05-31 19:52:36 +04:00
John Preston 1f0acae151 Show frequent/recent selected when preview. 2024-05-31 19:52:36 +04:00
John Preston 521c17b76c Show chat previews in suggestions. 2024-05-31 19:52:36 +04:00
John Preston f9f51b4e41 Show preview in Frequent Contacts. 2024-05-31 19:52:32 +04:00
John Preston 4e8895ddd9 Show "View as Messages" preview by Alt+Click. 2024-05-31 19:52:32 +04:00
John Preston ad342a5324 Extract chat preview as a SessionController part. 2024-05-31 19:52:25 +04:00
John Preston 5cfd86b829 Use Ui::Text::String to show topic names.
Fixes #27956.
2024-05-31 19:52:22 +04:00
John Preston 27eb3e45be Allow only t.me links in factchecks. 2024-05-31 19:52:22 +04:00
John Preston 4953246c5d Support touchscreen pinned chats reordering. 2024-05-31 19:52:18 +04:00
John Preston 4df5372dab Support chat preview on touchscreens. 2024-05-31 19:52:12 +04:00
John Preston 40fbd415ef Support collapsible blockquotes in Ui::Text::String. 2024-05-30 21:35:10 +04:00
John Preston 974bf99921 Allow editing spoiler/caption-above in EditCaptionBox. 2024-05-30 21:35:10 +04:00
John Preston 8c0351be4e Allow editing caption above/below media. 2024-05-30 21:35:10 +04:00
John Preston 67f7816088 Allow sending photo/video captions above media. 2024-05-30 21:35:10 +04:00
John Preston 924d80ecba Use message text rendering for media captions. 2024-05-30 21:35:10 +04:00
23rd d219bccf2b Fixed position of via bot header above reply in message view. 2024-05-30 21:35:10 +04:00
23rd 02bd2bca64 Removed display of credits button in settings when user has no credits. 2024-05-30 21:35:10 +04:00
23rd 57ecc2be1d Improved style of list of credits history entries for refunded entry. 2024-05-30 21:35:10 +04:00
23rd d3a01b6235 Improved style of list of credits history entries for entry photo. 2024-05-30 21:35:10 +04:00
23rd 58c060c59d Improved style of box for credits history entries for refunded entry. 2024-05-30 21:35:10 +04:00
23rd cd7507fb23 Respected accessibility of premium for credits purchasing. 2024-05-30 21:35:10 +04:00
23rd 9a5923676a Added posting of payment event to webview bot after credits sending. 2024-05-30 21:35:09 +04:00
John Preston c0f3d263a3 Remove webpage length limit for factcheck. 2024-05-30 21:35:08 +04:00
John Preston 056ba644ed Fix empty search placeholder. 2024-05-30 21:35:08 +04:00
23rd ebaffc333e Added initial api support of refund flag to credits history entries. 2024-05-30 21:35:08 +04:00
23rd be099880d8 Added initial ability to claim refund credits from history entries list. 2024-05-30 21:35:08 +04:00
John Preston 885dcf0b28 Update API scheme on layer 181. 2024-05-30 21:35:08 +04:00
John Preston a0d97f03cb Add factcheck footer support. 2024-05-30 21:35:08 +04:00
23rd c942034ca4 Added link to terms to box of credits history entries. 2024-05-30 21:35:08 +04:00
23rd 0bd780b20f Added fireworks effect on success credit sending. 2024-05-30 21:35:08 +04:00
23rd 7d75c25214 Added box for small balance of credits. 2024-05-30 21:35:08 +04:00
23rd 5defb9fb17 Fixed display of credit spending. 2024-05-30 21:35:08 +04:00
23rd 0549c8f037 Moved out list of top-up options to single place. 2024-05-30 21:35:08 +04:00
23rd 3c246e1e92 Split functions for credits settings. 2024-05-30 21:35:08 +04:00
23rd 58da617e3f Added description and optional photo to credits receipts. 2024-05-30 21:35:08 +04:00
23rd 1edf0ed70b Moved out widget of photo for credits history entries to single place. 2024-05-30 21:35:08 +04:00
23rd c27c567225 Added initial support for non-panel credits receipts. 2024-05-30 21:35:08 +04:00
23rd 93eff78cd6 Replaced all credits currency name at least with simple star. 2024-05-30 21:35:08 +04:00
23rd a2a27e115c Moved out box for credits history entries to single place. 2024-05-30 21:35:08 +04:00
23rd e9fb580ba4 Moved out credits currency to single place. 2024-05-30 21:35:08 +04:00
23rd d73313479b Partly reverted "Processed payments form with API scheme on layer 181.". 2024-05-30 21:35:08 +04:00
23rd e4e343b871 Removed unused Ui::IsCreditsInvoice. 2024-05-30 21:35:08 +04:00
23rd dda6b92bec Added initial ability to process non-panel payment forms. 2024-05-30 21:35:07 +04:00
23rd 3dd894ad30 Improved SendCreditsBox for data from credits payment form. 2024-05-30 21:35:07 +04:00
23rd f08ff92470 Added initial ability to provide data for non-panel payment forms. 2024-05-30 21:35:07 +04:00
23rd 923aaec085 Returned media to messages with credits invoice. 2024-05-30 21:35:07 +04:00
John Preston 1d3110228d Fix phrase in factcheck toast. 2024-05-30 21:35:07 +04:00
23rd 7194781bb8 Added api support for premium bot peer type for credits history entries. 2024-05-30 21:35:07 +04:00
John Preston 97a5e0c6ea Support limited formatting input in factcheck. 2024-05-30 21:35:07 +04:00
John Preston a3ef36f9f7 Fix build on Windows. 2024-05-30 21:35:07 +04:00
John Preston d13bf19b79 Show length limit when editing a factcheck. 2024-05-30 21:35:07 +04:00
John Preston 493f0450b4 Implement factcheck edition. 2024-05-30 21:35:07 +04:00
John Preston 74861a334d Show expand/collapse icon in factcheck. 2024-05-30 21:35:07 +04:00
John Preston a87a221f26 Force red for factcheck. 2024-05-30 21:35:07 +04:00
John Preston 923a9ec6a8 Show toggle-able factcheck footer. 2024-05-30 21:35:07 +04:00
John Preston b299881bf8 Track factcheck text and create media. 2024-05-30 21:35:07 +04:00
John Preston 5ee2bca616 Update API scheme on layer 181. 2024-05-30 21:35:07 +04:00
23rd d1e914fb30 Added initial implementation of box for credits history entries. 2024-05-30 21:35:07 +04:00
23rd 43cb315f47 Replaced PeerId with BareId in credits history entries. 2024-05-30 21:35:07 +04:00
23rd dcc52a7333 Moved out painting of userpic for credits entries to single place. 2024-05-30 21:35:07 +04:00
23rd 84cde1354d Slightly improved invoice view in messages for credits. 2024-05-30 21:35:07 +04:00
23rd 3d81414c71 Added initial implementation of box for sending credits. 2024-05-30 21:35:07 +04:00
23rd 69c48e2b5b Moved out credits balance widget to single place. 2024-05-30 21:35:07 +04:00
23rd 5ca9b74142 Fixed effect for successful payments in credits settings. 2024-05-30 21:35:07 +04:00
23rd e11755af46 Added credits balance to main session. 2024-05-30 21:35:07 +04:00
23rd 174fb62c32 Fixed purchases of credits. 2024-05-30 21:35:07 +04:00
23rd 0e30e306ff Added second type of stars to animation of mini stars. 2024-05-30 21:35:07 +04:00
23rd 5e29f382cd Fixed build with Xcode. 2024-05-30 21:35:07 +04:00
John Preston 8eb24f620d Update API scheme on layer 181. 2024-05-30 21:35:07 +04:00
John Preston 5adde6c93a Fix build on Windows. 2024-05-30 21:35:07 +04:00
23rd 42d6d0d58a Added tooltip to balance label in credits settings for high values. 2024-05-30 21:35:07 +04:00
23rd 6336df2bd6 Slightly improved code style for decimal counts. 2024-05-30 21:35:07 +04:00
23rd 030d35ea7e Added initial implementation of balance in credits settings. 2024-05-30 21:35:07 +04:00
23rd d81c3554cc Added multiple icons to credits topup options. 2024-05-30 21:35:07 +04:00
23rd ca37ffa086 Added list of credit history entries to credits settings. 2024-05-30 21:35:07 +04:00
23rd 154fe63b43 Implemented list of credit history entries. 2024-05-30 21:35:06 +04:00
23rd 65384d54f1 Added random debug data to credits history. 2024-05-30 21:35:06 +04:00
23rd 2bf8cb84d0 Added api support of credits status and credits history. 2024-05-30 21:35:06 +04:00
23rd f0a82de784 Fixed editing of last message with uploading media. 2024-05-30 21:35:06 +04:00
23rd 1a393ddebb Added star icons with gradient to main settings for premium buttons. 2024-05-30 21:35:06 +04:00
23rd 9b11b95c5b Added api support of invoice payments for credits. 2024-05-30 21:35:06 +04:00
23rd d0bfee6963 Added initial list for topup options in settings section for credits. 2024-05-30 21:35:06 +04:00
23rd f1636de572 Added initial api support for credits topup options. 2024-05-30 21:35:06 +04:00
23rd b5eb195f43 Added initial dummy settings section for credits. 2024-05-30 21:35:06 +04:00
23rd 4a0bffe618 Added ability to provide custom gradient to star in premium top bar. 2024-05-30 21:35:06 +04:00
23rd 53d97b4146 Added ability to provide custom gradient to colored premium stars. 2024-05-30 21:35:06 +04:00
23rd 2a224c839e Added initial phrases for settings section for credits. 2024-05-30 21:35:06 +04:00
23rd bc7aa91fbb Removed redundant constructor from Ui::Premium::TopBar. 2024-05-30 21:35:06 +04:00
23rd ac2f35f12b Processed payments form with API scheme on layer 181. 2024-05-30 21:35:06 +04:00
John Preston 39e03c3ca7 Update API scheme to layer181. 2024-05-30 21:35:06 +04:00
John Preston 1ce49df123 Fix saved / replies userpics in chats search. 2024-05-30 21:35:06 +04:00
John Preston 1865fd382c Show loading placeholders in chats list. 2024-05-30 21:35:06 +04:00
John Preston e00c6ecfb8 Show empty / placeholder in chats search. 2024-05-30 21:35:06 +04:00
John Preston 279db771cf Support dynamic search tabs with emoji. 2024-05-30 21:35:06 +04:00
John Preston 7b7438cd7b Make chats list tabs closer to each other. 2024-05-30 21:35:06 +04:00
John Preston 42d53e5543 Fix saved messages tags search. 2024-05-30 21:35:06 +04:00
John Preston fce520c9c0 Clear saved messages tags on cancel search. 2024-05-30 21:35:06 +04:00
John Preston b21bcb86cc Fix search from user in forums. 2024-05-30 21:35:06 +04:00
John Preston 7d61ab9412 Improve forum search support. 2024-05-30 21:35:06 +04:00
John Preston 701bf0d553 Fix searching with "from:" prefix. 2024-05-30 21:35:06 +04:00
John Preston 583bcca6a9 Fix forum search open by Ctrl+F. 2024-05-30 21:35:06 +04:00
John Preston 6a8edefc87 Fix some bugs in new chats search. 2024-05-30 21:35:06 +04:00
John Preston dd5643ac67 Start chats search rewrite. 2024-05-30 21:35:06 +04:00
John Preston 787cf7853e Implement simple chats search bar. 2024-05-30 21:35:06 +04:00
John Preston 5bfbae3afc Update API scheme on layer 180. 2024-05-30 21:35:06 +04:00
John Preston 363b700f1f Fix chat preview and new emoji interactions. 2024-05-30 21:35:05 +04:00
John Preston cde70b9807 Play effects in a separate layer over MainWidget. 2024-05-30 21:35:05 +04:00
John Preston f7ab8a2174 Fix Chat / Effect previews in custom themes. 2024-05-30 21:35:05 +04:00
John Preston a011a7c316 Fix sending scheduled effects. 2024-05-30 21:35:05 +04:00
John Preston 487fa9728a Fade in/out effect preview. 2024-05-30 21:35:05 +04:00
John Preston 8a58ded582 Show effect loading animation. 2024-05-30 21:35:05 +04:00
John Preston ec5d8b7373 More robust effect icon loading. 2024-05-30 21:35:05 +04:00
John Preston 732b67ca04 Implement effects paywalls. 2024-05-30 21:35:05 +04:00
John Preston d102d256a9 Implement effects search. 2024-05-30 21:35:05 +04:00
John Preston bbb3a51b74 Fix effect selector for !_useTransparency case. 2024-05-30 21:35:05 +04:00
John Preston d0d1ef9e66 Fix effect panel jump on expand. 2024-05-30 21:35:05 +04:00
John Preston b01244fc42 Show correct sticker effects title. 2024-05-30 21:35:05 +04:00
John Preston b92a05011f Show sticker effects in a StickerListWidget. 2024-05-30 21:35:05 +04:00
John Preston 5fb7992b04 Improve effect initial auto-play. 2024-05-30 21:35:05 +04:00
John Preston f371cd1af2 Use nice fake message for effect preview. 2024-05-30 21:35:05 +04:00
John Preston 144109db05 Show effect preview before sending. 2024-05-30 21:35:05 +04:00
John Preston e120ae6ae6 Pass effect to API for sending. 2024-05-30 21:35:05 +04:00
John Preston d1106e5ae6 Check effects availability in all SendMenu-s. 2024-05-30 21:35:05 +04:00
John Preston 396ba9a984 Initial code of attaching effect selector. 2024-05-30 21:35:05 +04:00
John Preston 92133e7f50 Show effect animation with correct geometry. 2024-05-30 21:35:05 +04:00
John Preston a19e71324b Implement basic effect animation. 2024-05-30 21:35:05 +04:00
John Preston f762634036 Support effects API, show icon in info. 2024-05-30 21:35:05 +04:00
John Preston ee4f83ffde Disable bottom-info reactions view. 2024-05-30 21:35:05 +04:00
John Preston f8188f360a Update API scheme to layer 180. 2024-05-30 21:35:05 +04:00
John Preston 2bbc7406da Beta version 5.0.6.
- Fix chat preview with non-default themes.
- Fix chat preview crash when scrolling up.
- Jump to chat from preview only by Double-Click.
- Show chat preview with Force Touch on macOS.
2024-05-30 19:06:51 +04:00
John Preston a9dd9aeb90 Use InnoSetup SignTool for setup signing.
Fixes #27583.
2024-05-30 19:03:12 +04:00
John Preston aa4156d1e7 Ignore shortcuts when preview is shown. 2024-05-30 19:03:08 +04:00
John Preston 4f5594c8cc ChatNext jumps to first chat if no chat opened.
Fixes #27963.
2024-05-30 19:03:04 +04:00
John Preston 0527e9a0f7 Fix adding bot as admin to channel. 2024-05-30 17:02:28 +04:00
John Preston 28cbb02b20 Jump to chat only by Double-Click on preview. 2024-05-30 17:02:26 +04:00
John Preston 7d636820ac Show last updated topic preview on Alt+Click. 2024-05-30 17:02:23 +04:00
John Preston e2b78b673b Fix unintentional search focus. 2024-05-30 17:02:19 +04:00
John Preston a9a0fe7cf5 Fix RTL chat names in preview. 2024-05-30 17:02:13 +04:00
John Preston 2b9e7a6b25 Show preview on Force-Click on macOS. 2024-05-30 17:02:09 +04:00
John Preston d6e827e982 Fix loading of chat preview messages. 2024-05-30 17:02:02 +04:00
John Preston d2e6003521 Ignore right click on preview. 2024-05-30 17:01:59 +04:00
John Preston 465fc42718 Fix chat preview in non-default themes. 2024-05-29 09:43:40 +04:00
John Preston 0dd6ff9d9b Beta version 5.0.5.
- Long press on chat userpic to show quick preview.
- Alt+Click on chat to show quick preview.
- Show author userpics in forwarded messages.
2024-05-29 00:03:45 +04:00
23rd 8a6b1677f4 Added userpic views to headers of forwarded messages. 2024-05-28 21:42:00 +04:00
John Preston 470b3a2cbd Fix preview showing on fast userpic click. 2024-05-28 21:42:00 +04:00
John Preston a60783eae3 Implement preview top and bottom. 2024-05-28 21:42:00 +04:00
John Preston de73d8766c Open chat on exact clicked message from preview. 2024-05-28 21:42:00 +04:00
John Preston cd7cfcdf2f Show chat preview on Alt+Click. 2024-05-28 21:42:00 +04:00
John Preston aee62c7591 Fix migrated history in chat preview. 2024-05-28 21:42:00 +04:00
John Preston 0f524ac67d Don't stick to bottom while loading down. 2024-05-28 21:42:00 +04:00
John Preston f223ae7eee Implement chats preview, show from unread. 2024-05-28 21:42:00 +04:00
John Preston 68df8448a2 Use arc_angles.h from lib_ui. 2024-05-28 21:42:00 +04:00
John Preston da31fef1ae Show long-press preview of topics. 2024-05-28 21:41:59 +04:00
John Preston 4427ae4306 Empty preview widget on long userpic press. 2024-05-28 21:41:59 +04:00
John Preston ef2aa05197 Allow HistoryView::ListWidget without SessionController. 2024-05-28 21:41:59 +04:00
John Preston e5132e3fe8 Version 5.0.4
- Fix reply to last message by Ctrl+Up in topics.
- Some other bug fixes.
2024-05-28 20:32:48 +04:00
23rd 3b6870396c Added ability to hide every sponsored message to premium users. 2024-05-28 20:30:40 +04:00
23rd f6b849e4f7 Added ability to add proxy from clipboard. 2024-05-28 20:30:40 +04:00
23rd 48e3802565 Improved labels for channel and group types with restricted content. 2024-05-28 20:30:40 +04:00
23rd 26ba7e57ce Fixed color of radial animation in audio files from shared media. 2024-05-28 20:30:40 +04:00
23rd 2605e754ff Added back button to cloud password step in intro. 2024-05-28 20:30:40 +04:00
23rd 9e85b1aa23 Fixed fake ability to hide webpage media with spoiler. 2024-05-28 20:30:40 +04:00
Ilya Fedin 88cd886ec8 Update lib_webview 2024-05-28 17:50:39 +04:00
John Preston adc536b81d Fix Ctrl+Up reply in topics / comments. 2024-05-28 15:01:01 +04:00
John Preston 275327c789 Version 5.0.3.
- Ctrl+Click on Reply in menu to Reply in another chat.
- Allow Zero-Width-Space character in text rendering.
- Fix creating custom links in the message field.
- Fix jump to the topic with last unread message.
- Fix newline entering via Shift+Enter on Linux.
- Fix forum search open by Ctrl+F.
2024-05-28 11:53:51 +04:00
John Preston 72471c74d0 Limit symbols that allow diacritics after them. 2024-05-28 11:45:21 +04:00
John Preston b9f63f80f1 Reply-in-another-chat by Ctrl+Click on Reply. 2024-05-28 10:59:46 +04:00
John Preston 32cd2120ac Allow zero width space in the middle of text.
Fixes #6959.
2024-05-28 10:54:20 +04:00
John Preston 7db9abf725 Fix forum search open by Ctrl+F. 2024-05-28 10:04:57 +04:00
John Preston f09a939a7c Improve fix for markup. 2024-05-27 22:24:19 +04:00
John Preston f1c1c900bf Fix newline regression on Linux. 2024-05-27 22:08:20 +04:00
John Preston a43143d01c Separate ForceDisable from LastCheckCrashed. 2024-05-27 17:54:23 +04:00
John Preston 7357b40ba1 Fix build with updated lib_ui. 2024-05-27 17:54:23 +04:00
Ilya Fedin ad6e34f3a4 Update lib_webview 2024-05-27 14:00:26 +04:00
John Preston daf30dcab8 Fix jump to last topic in case of unread topic click. 2024-05-27 13:33:25 +04:00
Ilya Fedin 0033ad749f Update lib_webview 2024-05-27 08:06:25 +04:00
Ilya Fedin 62c249015d Update lib_webview 2024-05-26 14:20:43 +04:00
AlexeyZavar f54c82bcb3 feat: round context menu a bit 2024-05-25 04:33:05 +03:00
AlexeyZavar 57b2c69ce6 Merge tag 'v5.0.2' into dev
# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/lib_ui
#	snap/snapcraft.yaml
2024-05-25 02:26:39 +03:00
John Preston 31fcca245f Version 5.0.2: Fix IME-to-search on macOS. 2024-05-24 20:54:10 +04:00
John Preston f4864cddc9 Fix possible crash in Settings of crashed web-app.
Fixes #27943.
2024-05-24 20:54:10 +04:00
John Preston 36db1105a2 Fix build with Xcode. 2024-05-24 16:09:01 +04:00
John Preston 364f62660c Version 5.0.2: Update the version number. 2024-05-24 15:26:18 +04:00
John Preston b67a1bca49 Version 5.0.2.
- Toggle chats search focus by Tab key.
- Unfocus empty search by Backspace key.
- Add a spoiler to already sent media when editing.
- Forward by drag-n-drop to frequent contacts / recent searches.
- Allow wide chats list in empty window
with narrow list when a chat is opened.
- Improve custom font support in the input fields.
- Fix input method typing from unfocused search.
- Fix possible media reordering on batch send.
- Fix crash in group emoji set saving.
- Fix possible hang on quit on macOS.
2024-05-24 15:13:04 +04:00
John Preston 000911546b Fix usernames drop on min user being received. 2024-05-24 14:50:00 +04:00
John Preston e26b8e7ebc Fix passcode lock glitch with new search. 2024-05-24 14:14:29 +04:00
John Preston f03935ad9a Kill hang processes in case of app quitting. 2024-05-24 14:08:14 +04:00
John Preston d91b75b8f8 Allow wide chats in empty window. 2024-05-24 12:55:48 +04:00
John Preston 4d4cf472c8 Fix crash in group emoji set saving. 2024-05-24 12:55:48 +04:00
John Preston 685c7a865e Use 64 iterations (like OpenSSL 3 for 2048 primes). 2024-05-24 12:55:48 +04:00
John Preston 0551550e61 Don't always open last topic in forums. 2024-05-24 12:55:48 +04:00
John Preston c3fab28e1c Improve scroll style for limited reaction selector. 2024-05-24 12:55:48 +04:00
John Preston 74db2167f9 Allow copy custom emoji from panel. 2024-05-24 12:55:48 +04:00
John Preston cedd8fc546 Fix incorrect replace media button show in reply. 2024-05-24 12:55:48 +04:00
John Preston db486e957c Fix group/channel Appearance button style. 2024-05-24 12:55:48 +04:00
John Preston 1c6f45d8d3 Fix drag-n-drop to frequent/recent contacts. 2024-05-24 12:55:48 +04:00
John Preston ba8bb2d50f Add .vscode to .gitignore. 2024-05-24 12:55:48 +04:00
John Preston ec6d6a78cf Tab toggles search focus, Backspace doesn't focus. 2024-05-24 12:55:48 +04:00
John Preston f10f3c08de Attempt to fix sending messages to broken topics. 2024-05-24 12:55:48 +04:00
John Preston 39c1da6642 Attempt to fix jump to unread in some cases. 2024-05-24 12:55:48 +04:00
John Preston 84ec2a5f74 Possibly fix wrong requests order. 2024-05-22 21:21:03 +04:00
Ilya Fedin 5e3e9ba824 Ensure Qt doesn't prevent quit due to ignored widget close events 2024-05-22 16:47:08 +04:00
Ilya Fedin 198528f79f Remove code needed for a removed patch 2024-05-21 14:20:43 +04:00
Ilya Fedin 8a5ad581b8 Update Qt to 6.7.1 on Linux 2024-05-21 14:20:43 +04:00
Ilya Fedin 7dbf8ca1f4 Remove unneeded Qt::WA_InputMethodEnabled
The widget already had it
2024-05-21 14:10:47 +04:00
dependabot[bot] df808df8d3 Bump actions/upload-artifact from 2 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 09:16:03 +04:00
Ilya Fedin 4fddaef112 Update lib_webview 2024-05-20 14:25:23 +04:00
John Preston 2bdc204c47 Fix geometry applying in webview windows. 2024-05-20 14:25:23 +04:00
Ilya Fedin 6734f99ba8 Update lib_ui & patches on Linux 2024-05-19 20:30:13 +04:00
Ilya Fedin af4e0178d0 Ensure window flags are set before calling SeparatePanel::setInnerSize
Setting window flags may lead to native window being re-created
2024-05-19 20:30:13 +04:00
Ilya Fedin 65b62485be Forward input method event from Dialogs::Widget to search field 2024-05-19 11:47:16 +04:00
Ilya Fedin 98b58c1168 Add missing binds for OpenGL shaders and buffers 2024-05-19 09:55:34 +04:00
Ilya Fedin ad13048cdc Update submodules 2024-05-16 22:20:08 +04:00
Ilya Fedin a753c1515b Remove unneeded wayland-client dependency from telegram part in snap 2024-05-16 22:20:08 +04:00
Ilya Fedin bd48e2fff2 Fix more package names in snap 2024-05-16 22:20:08 +04:00
John Preston 88ad1be4c3 Try to fix custom fonts in the input field. 2024-05-14 19:36:52 +04:00
John Preston 1f31d8032f Bring chosen font to the top of the box. 2024-05-14 19:36:52 +04:00
John Preston b5f5aed119 Fix search focus in a hidden window on launch.
Fixes #27853.
2024-05-14 19:36:52 +04:00
John Preston 213326a212 Update submodules. 2024-05-14 19:36:52 +04:00
23rd 264e35a6a8 Fixed rare crash in photo editor when editing media in message. 2024-05-14 17:19:39 +03:00
23rd 76137ca1cf Fixed link to premium section in box about sponsored messages. 2024-05-14 17:19:39 +03:00
23rd e4323ecd26 Slightly improved code style in processing of api text entities. 2024-05-14 17:19:39 +03:00
23rd b406e2b99b Fixed sender name for voices in overview layout when sender is hidden. 2024-05-14 17:19:39 +03:00
23rd c1c49e8ddc Added captions to voice messages in overview layout. 2024-05-14 17:19:39 +03:00
23rd 41e414af37 Removed transcribe buttons from scheduled messages. 2024-05-14 17:19:39 +03:00
23rd 2afb69e787 Fixed text state of reply bubble for messages with unwrapped media. 2024-05-14 17:19:39 +03:00
23rd 3e7d4af4a0 Fixed reply bubble width for short quotes. 2024-05-14 17:19:39 +03:00
23rd bc11c66777 Added ability to hide single sponsored message to premium users. 2024-05-14 17:19:39 +03:00
23rd 7a95b38d3c Fixed refreshing of file reference in api media spoiler editing module. 2024-05-14 17:19:39 +03:00
23rd 334fd4e951 Added ability to edit media with spoiled one without resending. 2024-05-14 17:19:39 +03:00
GoodDok 923e3ee808 Fix 25202: surrounding $PWD with double quotes
Added double quotes to work correctly with spaces in current directory's name
2024-05-14 14:43:38 +04:00
Robert-André Mauchin 3358673ba4 Add compatibility with FFMPEG 7.0
avio: Constify data pointees of write callbacks

avutil: remove deprecated FF_API_PKT_DURATION

Ref: https://github.com/FFmpeg/FFmpeg/commit/2a68d945cd74265bb71c3d38b7a2e7f7d7e87be5
     https://github.com/FFmpeg/FFmpeg/commit/02aea61d69d8f81bc285e2131bf25f96a3e27feb
     https://github.com/FFmpeg/FFmpeg/commit/b8fef7e9c520b3923b32813b6a82c154c74402dc
2024-05-14 14:39:29 +04:00
dependabot[bot] d28b9f10b4 Bump jlumbroso/free-disk-space from 1.3.0 to 1.3.1
Bumps [jlumbroso/free-disk-space](https://github.com/jlumbroso/free-disk-space) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/jlumbroso/free-disk-space/releases)
- [Commits](https://github.com/jlumbroso/free-disk-space/compare/f68fdb76e2ea636224182cfb7377ff9a1708f9b8...54081f138730dfa15788a46383842cd2f914a1be)

---
updated-dependencies:
- dependency-name: jlumbroso/free-disk-space
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 14:38:48 +04:00
Ilya Fedin 6ebbca58e8 Track major version for official GitHub helpers in actions 2024-05-14 09:54:25 +04:00
Ilya Fedin 15697f4f2b Fix libpng package name in snap 2024-05-08 12:10:37 +04:00
John Preston 2cb0651b04 Redirect IME to search on Windows. 2024-05-07 22:17:34 +04:00
John Preston 1f3a3ec04b Don't focus search when forum is opened. 2024-05-07 22:17:34 +04:00
John Preston c1a0172822 De-focus empty search by backspace. 2024-05-07 22:17:33 +04:00
GkvJwa 593e76479c Use jom build openssl on windows 2024-05-07 09:52:32 +04:00
dependabot[bot] 5d622b906e Bump ilammy/msvc-dev-cmd from 1.12.0 to 1.13.0
Bumps [ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/ilammy/msvc-dev-cmd/releases)
- [Commits](https://github.com/ilammy/msvc-dev-cmd/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: ilammy/msvc-dev-cmd
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 09:02:31 +04:00
dependabot[bot] 7e253314ec Bump jinja2 from 3.1.3 to 3.1.4 in /Telegram/build/docker/centos_env
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.3...3.1.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 23:29:00 +04:00
dependabot[bot] 78a05768d8 Bump dessant/lock-threads from 3 to 5
Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 3 to 5.
- [Release notes](https://github.com/dessant/lock-threads/releases)
- [Changelog](https://github.com/dessant/lock-threads/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dessant/lock-threads/compare/v3...v5)

---
updated-dependencies:
- dependency-name: dessant/lock-threads
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 23:28:48 +04:00
dependabot[bot] ddf6514a90 Bump actions/stale from 5 to 9
Bumps [actions/stale](https://github.com/actions/stale) from 5 to 9.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v5...v9)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 20:40:31 +04:00
dependabot[bot] 3847b97f80 Bump actions/cache from 3.0.11 to 4.0.2
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.11 to 4.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.11...v4.0.2)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 20:40:18 +04:00
dependabot[bot] 046bc03037 Bump actions/checkout from 3.1.0 to 4.1.4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 4.1.4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.1.0...v4.1.4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 20:40:02 +04:00
Ilya Fedin 7ff5f81b88 Try automatic actions update 2024-05-06 09:46:18 +04:00
AlexeyZavar b6de66611c feat: round context menu a bit 2024-05-05 18:28:10 +03:00
AlexeyZavar 166020723f chore: remove application font setting 2024-05-05 16:56:04 +03:00
AlexeyZavar 0bec9f742b fix: make it build 2024-05-05 16:55:09 +03:00
AlexeyZavar eeb5e5a206 Merge tag 'v5.0.1' into dev
# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/SourceFiles/info/profile/info_profile_actions.cpp
#	Telegram/lib_ui
#	snap/snapcraft.yaml
2024-05-04 21:49:27 +03:00
John Preston fb444e7dd4 Version 5.0.1.
- Fix several crashes in new interfaces.
- Fix monospace font size.
- Fix possible problem with underline font size.
2024-05-04 19:08:30 +04:00
23rd c4f0db5bc5 Fixed possible crash on slow resolving message from personal channel. 2024-05-04 18:13:30 +04:00
23rd a866ba8cdd Fixed crash on restricting users from moderation box. 2024-05-04 18:13:28 +04:00
John Preston 129d356909 Fix scrolling expanded frequent contacts. 2024-05-04 18:13:04 +04:00
Ilya Fedin 7289292f02 Update lib_ui & patches on Linux 2024-05-04 14:05:09 +04:00
Ilya Fedin 638e88ec79 Revert "Use latest mesa in snap"
This reverts commit b246328dcf.
2024-05-04 14:05:09 +04:00
John Preston 19ead551d9 Fix a typo bug in replies section scrolling. 2024-05-03 21:04:06 +04:00
John Preston fccaa587e1 Fix adjustment of size for modified fonts. 2024-05-03 21:04:06 +04:00
23rd 1709fcd0df Guarded personal channel info from possible crash on deleting message. 2024-05-03 21:04:06 +04:00
23rd de1f222bac Fixed rescheduling of selected and grouped scheduled messages. 2024-05-03 21:04:06 +04:00
Ilya Fedin 5e1f0e9f7f Move waiting for answer action 30 minutes later than lock threads 2024-05-03 19:59:24 +04:00
Alan Pope e3a14d432b Be consistent with libgtk-3-0t64
The reason it worked without explicitly updating this one is because the deb of libgtk-3-0t64 has a 'replaces' line for libgtk-3-0 - which nullifies this entry, as both were specified. But, you're right, looks better to have the right package in there.
2024-05-03 19:59:07 +04:00
Alan Pope 2b013c108f Fixes for unable to find gtk-query-immodules-3.0
The package has been updated for 2038 t64 update. This fixes that. 

Successfully build telegram 5.0.0 in arm64 after the fixes in this PR.
2024-05-03 19:59:07 +04:00
Alan Pope 0194687181 fix: Incorrect package name
Noble has libvpx9, not vpx8.

https://packages.ubuntu.com/search?keywords=libvpx9
2024-05-03 19:59:07 +04:00
John Preston bb47f4659d Don't adjust monospace font size. 2024-05-02 19:36:59 +04:00
John Preston 2b580d29ae Add .qoi to list of image extensions. 2024-05-02 17:17:40 +04:00
John Preston b7e52119bc Add .jxl to the list of image extensions. 2024-05-02 16:35:29 +04:00
John Preston fd633ecb49 Version 5.0.
- Choose custom font family in Settings > Chat settings > Font family.
- Show "Frequent contacts" when you focus the search field.
- Show "Recent chats" when you focus the search field.
- Show "Channels" list and similar channels.
- Premium users can use animated emoji in polls.
- Group admins can mass-moderate many messages.
- Fix frequent crashes on some Linux systems.
2024-05-02 14:11:20 +04:00
John Preston 9c77346f36 Fix build with Xcode and GCC. 2024-05-02 14:11:20 +04:00
John Preston 641e74763f Revert non-production-ready prepare.py changes.
Accidentally commited in b9b7d9e337.
2024-05-02 12:17:57 +04:00
John Preston 2e71427427 Improve font size edge cases. 2024-05-02 12:05:46 +04:00
John Preston 95ec0633ed Use custom-adjusted font metrics for custom fonts.
Fixes #27814.
2024-05-02 11:33:47 +04:00
23rd 14e8b8fb91 Fixed spam reporting in moderation box. 2024-05-02 04:09:25 +03:00
23rd d40951f068 Added ability to moderate non-users to moderation box. 2024-05-02 04:09:25 +03:00
23rd ab85d18cc8 Added support of personal channel with message. 2024-05-02 04:09:25 +03:00
23rd 6becaaa953 Slightly improved view style of giveaway results in dialogs list. 2024-05-02 04:09:25 +03:00
23rd 26e8c29f40 Moved formatting of dialog last date to td_ui. 2024-05-02 04:09:25 +03:00
John Preston 47800ee02d Improve font size selection a bit. 2024-05-01 19:09:54 +04:00
John Preston 12a24dd473 Fix possible crash in common groups list.
Currently Data::Session::processChat() may change adminRights(),
that may change Data::CanSendAnyOf(peer, ...), that may lead to
Window::SessionController::updateThirdColumnToCurrentChat() call,
that destroys current third column to replace it with another one.

If common groups list was opened in the third column this will crash.

Fixes #27640.
2024-05-01 17:52:40 +04:00
23rd ad6321d3ae Fixed possible crash in moderate box. 2024-05-01 14:10:37 +03:00
John Preston 7e071c770f Fix possible crash with custom wallpapered peers. 2024-05-01 14:38:06 +04:00
John Preston a62d1dfa63 Focus chats search by Ctrl[Cmd]+F. 2024-05-01 14:38:05 +04:00
John Preston b3eb1dbc14 Revert "Toggle search focus by escape."
This reverts commit 72d5a9b3e0.
2024-05-01 14:38:05 +04:00
Ilya Fedin 3170a45158 Increase snapcraft verbosity 2024-05-01 14:06:23 +04:00
John Preston 32483fa13b Just focus the search field on Space. 2024-05-01 12:57:47 +04:00
John Preston 9166a1c3a6 Update Linux Qt patches. Hope fixes crashes. 2024-05-01 12:57:07 +04:00
GitHub Action 6fa0afff37 Update User-Agent for DNS to Chrome 124.0.0.0. 2024-05-01 12:47:51 +04:00
Ilya Fedin bc649af941 Schedule no-response action runs at different times
To avoid rate limits
2024-05-01 12:47:42 +04:00
John Preston 16ce5ef046 Greeting category first in ChatIntro setup. 2024-05-01 12:47:20 +04:00
John Preston bb6fd4bc4d Update scheme, new sticker categories. 2024-05-01 12:47:20 +04:00
John Preston 63e1731d7c Fix premium preview bullet-dots.
Regression was introduced in 88751896af.
2024-05-01 12:47:20 +04:00
John Preston b9b7d9e337 Implement live location view. 2024-05-01 12:47:20 +04:00
23rd ef8c07e6eb Added ability to translate selected text in profile section. 2024-04-30 17:35:34 +03:00
23rd 20a13663a6 Slightly improved style of rpl text mapping. 2024-04-30 17:35:04 +03:00
23rd 2f0aa6ef05 Removed state sending of low level of battery to call participant. 2024-04-30 16:49:17 +03:00
23rd 62bd1354dc Replaced box for leaving or deleting chat with generic box. 2024-04-28 20:14:26 +03:00
23rd be255f1d09 Added to moderate box number of all messages that will be deleted. 2024-04-28 20:14:26 +03:00
23rd b8b02b2285 Replaced list of history items for sending now with sorted by date. 2024-04-28 13:33:04 +03:00
23rd e0db0642bd Fixed crash when deleting message from non-user. 2024-04-27 16:39:13 +03:00
23rd e81465a54e Added Enter shortcut to moderation box for confirmation. 2024-04-27 13:31:00 +03:00
23rd 6e67cfc7be Fixed possible crash in moderation box. 2024-04-27 12:59:36 +03:00
John Preston c0db5ee98a Beta version 4.16.10: Fix GCC build. 2024-04-26 23:41:28 +04:00
John Preston 372b3da09c Beta version 4.16.10.
- Group admins can mass-moderate many messages.
- Premium users can use animated emoji in polls.
- Revert the default "Open Sans" font to 1.10.
- Several crash fixes and small improvements.
2024-04-26 20:55:06 +04:00
John Preston 79532954dc Allow a bit more font size adjusting. 2024-04-26 20:18:30 +04:00
23rd aff2be605e Removed item for poll creation from menu when it is impossible. 2024-04-26 19:15:03 +03:00
John Preston 363c191a6e Skip media bottom skip in IV. 2024-04-26 20:12:30 +04:00
John Preston 2949cdab61 Don't request IV two times in a row. 2024-04-26 20:12:29 +04:00
John Preston 7addcf2d25 Add IV footer. 2024-04-26 20:12:29 +04:00
John Preston a272807a99 Remove "Create poll" button in Replies chat.
Fixes #27817.
2024-04-26 20:12:29 +04:00
23rd c803603de4 Added ability to insert custom emoji to polls. 2024-04-26 20:12:29 +04:00
23rd e6c22ec1ca Added api support for custom emoji in polls. 2024-04-26 20:12:29 +04:00
John Preston b3ae843f0e Update API scheme to layer 179. 2024-04-26 20:12:29 +04:00
John Preston 12a78c1f45 Allow pasting text to the unfocused search. 2024-04-26 20:12:29 +04:00
23rd 612b81ee87 Fixed allowed reactions for channel posts in linked chats. 2024-04-26 20:12:29 +04:00
23rd e5b91d2f3d Added entry points for moderation box. 2024-04-26 20:12:29 +04:00
23rd 82293c98eb Added arrow icon to divider link in moderation box. 2024-04-26 20:12:29 +04:00
23rd 629da68cfc Added api support to moderation box. 2024-04-26 20:12:29 +04:00
23rd 643ecd2c2c Implemented initial ui of moderation box. 2024-04-26 20:12:29 +04:00
Ilya Fedin dd1cb00c62 Update snap to core24 2024-04-26 18:39:56 +04:00
23rd 2c4d8418c1 Removed unused code for sponsored messages. 2024-04-26 11:21:41 +04:00
23rd 9fcb5d6f31 Added emoji button to input field for peer title edit. 2024-04-26 11:21:41 +04:00
23rd 38fc6bfbb9 Added special mode to emoji list widget to exclude non-unicode emoji. 2024-04-26 11:21:41 +04:00
23rd 804991a69c Added universal duration to styles. 2024-04-26 11:21:41 +04:00
23rd 7388f46adf Fixed display of subscribers count in dialogs suggestions. 2024-04-26 11:21:41 +04:00
John Preston 10c427127e Fix accidental search focusing. 2024-04-26 11:10:12 +04:00
John Preston c6d034174b Support separate webview storages. 2024-04-26 08:58:42 +04:00
Ilya Fedin 471831bcd6 Revert "Remove not really needed notification capability checks"
This reverts commit abdfa4f785.
2024-04-25 15:07:51 +04:00
Ilya Fedin b1e64419a5 Fix setting application icon in Linux notifications 2024-04-25 11:31:43 +04:00
Ilya Fedin e2f17f1131 Remove unneeded includes from notifications_manager_linux 2024-04-25 11:31:43 +04:00
John Preston ae4a73a15b Rollback OpenSans to 1.10. 2024-04-24 22:20:22 +04:00
Kolya a84ca00270 fix typo 2024-04-24 19:18:33 +04:00
John Preston c16d820b88 Move OpenSSL probing before crash reporter. 2024-04-24 19:12:46 +04:00
John Preston ef614150d5 Remove dead code in lib_ui. 2024-04-24 17:44:51 +04:00
John Preston b46ca1ec17 Use different font fallback algo on Windows. 2024-04-24 17:44:40 +04:00
John Preston d5a347ede7 Try cancelling the new search by mouse back button. 2024-04-24 17:41:12 +04:00
John Preston 72d5a9b3e0 Toggle search focus by escape. 2024-04-24 16:56:20 +04:00
John Preston e6d72b4861 Un-focus chats search on empty history click. 2024-04-24 16:54:10 +04:00
John Preston 3da51b1bc9 Fix crash on quit in sponsored messages. 2024-04-24 16:37:27 +04:00
John Preston 17b7db6219 Request 64 frequent contacts instead of 32. 2024-04-24 16:37:27 +04:00
John Preston 8353180161 Fix phrase cut-off in QR login. 2024-04-24 16:37:27 +04:00
John Preston f675a8dcf7 Attempt to fix a couple of crashes. 2024-04-24 16:37:27 +04:00
John Preston 493f1d69e2 Fix cancel search button overlap. 2024-04-24 16:37:27 +04:00
John Preston 331e8c3ec6 Beta version 4.16.9.
- Show "Frequent contacts" when you focus the search field.
- Show "Recent chats" when you focus the search field.
- Show "Channels" and channel recommendations.
- Allow changing font in Settings > Chat settings > Font family.
2024-04-23 23:14:19 +04:00
John Preston 56bce70558 Fix "long time ago" for users who blocked me. 2024-04-23 21:47:57 +04:00
John Preston d82e48f8e4 Improve ChooseFontBox navigation. 2024-04-23 19:17:42 +04:00
John Preston 97ecc57be8 Add choose font settings. 2024-04-23 19:17:42 +04:00
John Preston 25bd2b145b Update submodules. 2024-04-23 19:17:42 +04:00
John Preston 7111c92ae7 Fix keyboard navigation in top peers. 2024-04-23 19:17:42 +04:00
John Preston e066cf1589 Add "Show all" for top peers. 2024-04-23 19:17:41 +04:00
John Preston 6f328b2ef8 Fix inline query draft applying. 2024-04-23 19:17:41 +04:00
23rd 7a6c55bd8a Fixed color of icon for replies with media story. 2024-04-23 19:17:41 +04:00
23rd b35d3f57fe Slightly improved style of sub-button in sponsored messages. 2024-04-23 19:17:41 +04:00
23rd eef65af173 Slightly simplified meson usage on macOS in prepare.py. 2024-04-23 19:17:41 +04:00
23rd bea715b41c Added ICCv4 with Little CMS on macOS. 2024-04-23 19:17:41 +04:00
23rd 7be68ca82c Updated Qt to 6.2.8 on macOS. 2024-04-23 19:17:41 +04:00
John Preston 287d5a7413 Fix shadow below Chats/Channels. 2024-04-23 19:17:41 +04:00
John Preston 1448cea01c Fix ripple in active recommendation row. 2024-04-23 19:17:41 +04:00
John Preston 768e8b457b Improve second-time choose of toppeers. 2024-04-23 19:17:41 +04:00
John Preston 05474f4a3f Improve filter switching with toppeers. 2024-04-23 19:17:41 +04:00
John Preston 8acada9b0f Fix toppeers animation with expanded stories. 2024-04-23 19:17:41 +04:00
23rd a86e7f035f Slightly improved style of inner box for channel earn history entries. 2024-04-23 19:17:41 +04:00
John Preston 9caff93c35 Fix build for Xcode. 2024-04-23 19:13:48 +04:00
John Preston e6ba85e112 Keyboard navigation in channels/recommendations. 2024-04-23 19:13:48 +04:00
John Preston 046803dbed Fix rotation reading in FFmpeg. 2024-04-23 19:13:48 +04:00
John Preston 615f4b1d1c Ignore pageBlockUnsupported blocks. 2024-04-23 19:13:48 +04:00
John Preston a11535806d Always show cancel search when focused. 2024-04-23 19:13:48 +04:00
John Preston 34a7169b4f Make unread badges on top peers nicer. 2024-04-23 19:13:47 +04:00
John Preston 4f365c73ad Support active selection in recommendations. 2024-04-23 19:13:47 +04:00
John Preston 705bd9693d Load recommendations on demand. 2024-04-23 19:13:47 +04:00
John Preston a88770a8ec Don't close recommendations. 2024-04-23 19:13:47 +04:00
John Preston da423b5bd2 Add a general FastShareLink method. 2024-04-23 19:13:47 +04:00
John Preston 56080bd0e4 Fix boost group link handling for forums. 2024-04-23 19:13:47 +04:00
John Preston 63f66a1369 Show "Boost" button in boost group links. 2024-04-23 19:13:47 +04:00
John Preston ca1a30196e Fix LinkButton resizing. 2024-04-23 19:13:47 +04:00
John Preston b2d8e2a1e6 Initial version of channels/recommendations. 2024-04-23 19:13:47 +04:00
John Preston 2ab8bb13c5 Fix links preview. 2024-04-23 19:13:47 +04:00
23rd 3a2c5c6d0a Increased size of stickerset preview in webpages. 2024-04-23 19:13:47 +04:00
23rd ed13a325e9 Added stickerset preview to webpages. 2024-04-23 19:13:47 +04:00
23rd f43f99cff2 Added initial api support of stickerset attribute in web pages. 2024-04-23 19:13:47 +04:00
John Preston a3b8397361 Close chat/media if thrown out by admin. 2024-04-23 19:13:47 +04:00
John Preston 4fb03e532c Optimize stories list generation. 2024-04-23 19:13:47 +04:00
John Preston 645ad5e1bd Update pinned icon in stories list. 2024-04-23 19:13:47 +04:00
John Preston 9036e9e8e3 Show pinned icon in stories. 2024-04-23 19:13:47 +04:00
John Preston 468d8b04d6 Implement stories pin-to-top. 2024-04-23 19:13:47 +04:00
John Preston 4b98ab1246 Fix build with simplified ads. 2024-04-23 19:13:46 +04:00
John Preston d33e3dc13a Rename Story::pinned to Story::inProfile. 2024-04-23 19:13:46 +04:00
23rd df16e7c00b Added ability to change reactions limit in channels. 2024-04-23 19:13:46 +04:00
23rd 225c0e0af3 Added initial api support of reactions limit in channels and groups. 2024-04-23 19:13:46 +04:00
23rd 5543927042 Added ability to enable sponsored messages for premium self. 2024-04-23 19:13:46 +04:00
23rd 72b274a2bf Added support of simplified constructor for MTP sponsored message. 2024-04-23 19:13:46 +04:00
John Preston ac15990b48 Update API scheme to layer178, ads broke build. 2024-04-23 19:13:46 +04:00
John Preston 7387dfdd9c Don't create top/recent peers unnecessary. 2024-04-23 19:13:46 +04:00
John Preston 74a7e7d1b4 Fix non-intentional chats list search focus. 2024-04-23 19:13:46 +04:00
John Preston a0a9de1d18 Cancel search on switching folders. 2024-04-23 19:13:46 +04:00
John Preston 360366ba9e Fix opening forums from recent peers. 2024-04-23 19:13:46 +04:00
John Preston 0180fe9468 Animate search suggestions. 2024-04-23 19:13:46 +04:00
John Preston 19f5d95a3c Implement keyboard navigation for recent peers. 2024-04-23 19:13:46 +04:00
John Preston 051ca51d3b Allow clearing search results. 2024-04-23 19:13:46 +04:00
John Preston 2a6ff9203b Implement basic recent search results. 2024-04-23 19:13:46 +04:00
John Preston 2e0529bd9a Add data component for RecentPeers. 2024-04-23 19:13:46 +04:00
John Preston e24ab4f1ab Allow saving emoji to files in debug builds. 2024-04-23 19:13:46 +04:00
John Preston 3dbadeb232 Allow opening top peers in a new window. 2024-04-23 19:13:46 +04:00
John Preston 4cdd939028 Cache topPeers locally. 2024-04-23 19:13:46 +04:00
John Preston c11f4efc5c Support disabling top peers completely. 2024-04-23 19:13:46 +04:00
John Preston e1c21b908c Add keyboard navigation to top peers. 2024-04-23 19:13:46 +04:00
John Preston a6c1def6fe Add ripples to top peers. 2024-04-23 19:13:46 +04:00
John Preston 19ae76d8de Top peers context menu. 2024-04-23 19:13:46 +04:00
John Preston 56e28feb00 Top peer realtime badges. 2024-04-23 19:13:45 +04:00
John Preston b259c566b7 Top peer unread badges and online indicators. 2024-04-23 19:13:45 +04:00
John Preston 18598f8dca Initial version of top peers. 2024-04-23 19:13:45 +04:00
John Preston 11e4c45969 Don't collapse chats list on window unfocus. 2024-04-23 19:13:45 +04:00
John Preston 39658ffe52 Allow narrow chats width without main section. 2024-04-23 19:13:45 +04:00
John Preston 2f03b9aa29 Make dialogs filter onfocused by default. 2024-04-23 19:13:45 +04:00
John Preston dc438cff23 Always export file_name in json. 2024-04-23 19:13:45 +04:00
John Preston 18f5521be5 Don't look for SDL when building on macOS. 2024-04-23 19:13:45 +04:00
Ilya Fedin bae9af1076 Switch crash reporter to system fonts
This should prevent nested crashes when loading custom fonts
2024-04-23 11:01:19 +04:00
Ilya Fedin 8d2805f226 Set font weight in crash reporter 2024-04-23 10:10:43 +04:00
Ilya Fedin 0ad18c8182 Get rid of direct Wayland usage
This should get rid of a very nasty vector of misbehaving and quite a lot of code which is boilerplate over Wayland protocols at the price of losing support of niche features

Most of things served by xcb code on X11 is served by portal code on Wayland, hopefully this tendention will continue and we will be fine just with glib which provides D-Bus and other basic APIs
2024-04-22 11:04:02 +04:00
Ilya Fedin 9046b2cafb Stop using the plasma-shell protocol
Looks like this isn't really correct in combination with xdg-shell
2024-04-22 10:59:16 +04:00
Ilya Fedin 3d994b58a0 ShowXDPOpenWithDialog -> UnsafeShowOpenWith 2024-04-21 03:14:34 +04:00
Ilya Fedin 4310c4978e Fix macOS packaged action 2024-04-19 17:41:07 +04:00
AlexeyZavar 5566a8ca0a fix: hide Read Message for service 2024-04-19 03:40:59 +03:00
AlexeyZavar f5470cd235 fix: read topics correctly 2024-04-19 03:37:47 +03:00
AlexeyZavar 1c275caf9d fix: use MakeConfirmBox 2024-04-19 02:55:33 +03:00
AlexeyZavar 39e3fcb553 fix: check time before appending 2024-04-19 02:46:28 +03:00
AlexeyZavar 11abaac7c1 fix: hide notifications from blocked users
e.g. when in shared group chats with enabled notifications
sound still plays, lazy to fix that
2024-04-19 02:18:38 +03:00
AlexeyZavar b054093899 fix: hide IV in streamer mode 2024-04-19 02:08:15 +03:00
AlexeyZavar 7d57e52469 fix: hide My Stories with disableStories 2024-04-19 01:56:08 +03:00
AlexeyZavar a0c787468b fix: don't hide messages if it's a dialog with blocked user 2024-04-19 01:50:45 +03:00
AlexeyZavar 3f79ccbcaf fix: don't select filtered messages 2024-04-19 01:45:11 +03:00
AlexeyZavar b6c966f18b feat: improve hide from blocked users 2024-04-19 01:21:52 +03:00
AlexeyZavar 1c85a81f1f feat: hide messages from blocked users
Co-authored-by: Ilya Fedin <fedin-ilja2010@ya.ru>
2024-04-19 00:05:00 +03:00
AlexeyZavar b4c5963a1a chore: update sqlite3 2024-04-18 22:54:01 +03:00
AlexeyZavar 299833ca3d feat: add fade animation for icon picker 2024-04-18 22:45:30 +03:00
AlexeyZavar a48534b51a feat: rework copyUsernameAsLink 2024-04-18 22:17:36 +03:00
AlexeyZavar daec2545b4 fix: more accurate channel badge 2024-04-18 20:58:53 +03:00
23rd 01bfa46729 Fixed display of default box for message schedule in correspond window. 2024-04-18 11:57:25 +04:00
Kolya 3510ca7184 Don't use/link libsharpyuv in libavif 2024-04-18 09:23:15 +04:00
Ilya Fedin 8d7845daa1 Use --shallow-submodules in Docker 2024-04-18 09:13:37 +04:00
Ilya Fedin cb5fdac0da Replace mozjpeg with jpegli on Linux 2024-04-17 23:45:15 +04:00
AlexeyZavar 5234c8af1a feat: hide proxy sponsor 2024-04-17 04:41:12 +03:00
AlexeyZavar 80cadf8f7d fix: hide irrelevant items 2024-04-17 04:25:20 +03:00
AlexeyZavar 7cc14bda52 chore: remove upload boost
Increasing chunks size, `kMaxUploadPerSession`, etc. don't change the speed, only if slows down.
Maybe changing `kAcceptAsFastIfTotalAtLeast` could give a boost. Didn't check.

In some circumstances, speed could be worse than on the AyuGram `v4.16` with boost, but it's rare.
But the upload speed is good, so upload boost removed.
2024-04-17 04:06:49 +03:00
AlexeyZavar c55cab3b1a fix: hideAllChats
Co-authored-by: c0re100 <corehusky@gmail.com>
2024-04-17 03:05:05 +03:00
AlexeyZavar 77d20c11a7 fix: update submodule 2024-04-17 03:04:14 +03:00
AlexeyZavar fe1babe437 Merge tag 'v4.16.8' into dev
# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/lib_ui
#	snap/snapcraft.yaml
2024-04-17 02:41:49 +03:00
AlexeyZavar 60a96bf9d6 fix: make it build 2024-04-17 02:38:43 +03:00
John Preston 78c8d0562b Version 4.16.8: Fix build on Linux. 2024-04-16 23:23:11 +04:00
John Preston bb0280f096 Revert "Replace mozjpeg with jpegli in snap"
This reverts commit f57e2edf2a.
2024-04-16 23:22:55 +04:00
John Preston 566b53ce9f Revert "Clean remainings of mozjpeg in snapcraft.yml"
This reverts commit da1909cc1d.
2024-04-16 23:22:43 +04:00
John Preston ec95db0945 Revert "Replace mozjpeg with jpegli in Docker"
This reverts commit a1e2e3d011.
2024-04-16 23:00:08 +04:00
John Preston a0d7d07543 Version 4.16.8.
- Fix in-app playing of some video and audio files.
- Fix crash on Linux opening chats with custom backgrounds.
- Fix crash on quit after using scheduled messages.
2024-04-16 20:15:32 +04:00
John Preston fe73bf9053 Fix ripples in channel comments buttons. 2024-04-16 20:14:04 +04:00
John Preston 49c9e08b6c Enforce video/audio extension by mime type. 2024-04-16 20:14:01 +04:00
John Preston abcf55c498 Check chat background read result. 2024-04-16 20:13:55 +04:00
John Preston 849ce310c4 Jump by keyboard between time input fields. 2024-04-16 20:13:02 +04:00
John Preston a3e593b747 Fix crash in scheduled messages tear-down. 2024-04-16 20:12:03 +04:00
23rd 5433f95eda Simplified creation of label with custom emoji. 2024-04-16 03:44:00 +03:00
23rd 0459196982 Moved out level meter widget to td_ui. 2024-04-16 03:43:39 +03:00
23rd 6f1457d30d Fixed phrase of placeholder for message edition mode. 2024-04-15 23:56:37 +03:00
23rd ce596e29c4 Fixed opening message from media player widget in corresponding window. 2024-04-15 23:41:00 +03:00
23rd 86b9d16747 Added additional note for macOS keys to json of custom shortcuts. 2024-04-15 23:30:57 +03:00
John Preston 06911ae42a Version 4.16.7.
- Reimplement file open confirmations.
2024-04-15 17:56:45 +04:00
John Preston af2cb9b757 Fix possible unhandled exception in highlighting. 2024-04-15 17:56:45 +04:00
John Preston 6a28cd1a35 Reimplement file open confirmations. 2024-04-15 12:07:27 +04:00
23rd f4a09a9ca0 Fixed display of growth rate in statistics info for huge values. 2024-04-15 11:20:30 +04:00
23rd a35f020f56 Moved out ScheduledMessages module to components submodule. 2024-04-15 11:20:30 +04:00
23rd 3d48111368 Moved out SponsoredMessages module to components submodule. 2024-04-15 11:20:30 +04:00
23rd 39ed7d7f4c Increased clickable area for each item in EditPeerHistoryVisibilityBox. 2024-04-15 11:20:30 +04:00
23rd abe83ccb8f Moved inaccessible groups in box for user's own groups to sub-list.
Fixed #27729.
2024-04-15 11:20:30 +04:00
23rd d1be7c1ff7 Simplified management of PasscodeBox within customCheckCallback. 2024-04-15 11:20:30 +04:00
23rd 1c223e570a Slightly improved code style for long equality expressions. 2024-04-15 11:20:30 +04:00
23rd a37cbd7d05 Initially refactored statistics module to simplify value types changing. 2024-04-15 11:20:30 +04:00
23rd 7ffa9844e2 Fixed currency formatting for channel earn info section. 2024-04-15 11:20:30 +04:00
23rd bdf5872f04 Fixed opening channel earn info section for admins. 2024-04-15 11:20:30 +04:00
Ilya Fedin da1909cc1d Clean remainings of mozjpeg in snapcraft.yml 2024-04-15 10:11:54 +04:00
Ilya Fedin a503197352 Remove XCBSetDesktopFileName
This is done by Qt nowadays
2024-04-15 10:11:30 +04:00
Nyan d9d9a8f49d Update data_document_resolver.cpp
Added the LEXE and WLUA extensions to the IsExecutableName function for Windows. Those are registered by default on Windows devices with LUA installed
2024-04-13 23:45:03 +04:00
AlexeyZavar 6a02bd66a9 Merge tag 'v4.16.6' into dev
# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp
#	Telegram/SourceFiles/core/version.h
#	Telegram/SourceFiles/info/profile/info_profile_actions.cpp
#	Telegram/SourceFiles/mtproto/facade.h
#	Telegram/SourceFiles/storage/file_upload.cpp
#	Telegram/SourceFiles/storage/file_upload.h
#	Telegram/SourceFiles/window/window_main_menu.cpp
#	Telegram/lib_ui
#	snap/snapcraft.yaml
2024-04-12 14:35:06 +03:00
Ilya Fedin f57e2edf2a Replace mozjpeg with jpegli in snap 2024-04-11 12:35:47 +04:00
Ilya Fedin a1e2e3d011 Replace mozjpeg with jpegli in Docker 2024-04-11 12:35:47 +04:00
Ilya Fedin 5e546d1198 Update libjxl in Docker & snap 2024-04-11 12:35:47 +04:00
Ilya Fedin 90405f3ebc Install protobuf in Docker 2024-04-11 12:15:55 +04:00
Nyan 11b57ff7d3 Update data_document_resolver.cpp
The correct python zipapp extension on windows is pyzw, this typo could lead to executing code in the client device without proper warning
2024-04-11 11:24:15 +04:00
Ilya Fedin fe06cd63ac Lock event loop 2024-04-09 20:48:47 +04:00
John Preston 6c9d5e1499 Improve clipboard QR code image logo quality. 2024-04-09 19:05:02 +04:00
John Preston 6ed910de9f Version 4.16.6.
- Show custom emoji preview on long press.
- Fix resume chat bot button disappearance.
- Fix GIF files playback. (regression in 4.16.3.beta)
2024-04-09 15:20:16 +04:00
John Preston a506b8b25c Support t.me/username?text=.. links. 2024-04-09 15:20:10 +04:00
John Preston 170ebb57c6 Preview custom emoji on long press from the panel. 2024-04-09 12:11:07 +04:00
John Preston 29dd574e22 Fix toggling chatbot replying, fix saving. 2024-04-09 11:55:52 +04:00
John Preston 72770aa76d Add GIF parser to FFmpeg build.
Fixes #27722.
2024-04-09 11:29:19 +04:00
John Preston 7f1c319aee Add interactive mode to prepare script. 2024-04-09 11:29:16 +04:00
John Preston 60805bd916 Version 4.16.5.
- Fix editing privacy for groups and channels invitations.
- Possible fix for the network unresponsiveness after sleep.
- Possible fix for wide range of memory allocator crashes on Linux.
2024-04-08 22:31:07 +04:00
Ilya Fedin 10272ee0cf Revert "Replace jemalloc with scudo"
This reverts commit 960761ef37.
2024-04-08 21:57:25 +04:00
John Preston 7c44cda76e Fix premium users deselection in multi-select field. 2024-04-08 21:56:56 +04:00
John Preston 0152d2c48e Fix possible temp auth key bind freeze. 2024-04-08 21:56:56 +04:00
23rd c5febce548 Moved out some functions for main menu to separated files. 2024-04-08 17:34:58 +03:00
23rd 129b07c2c0 Improved style of box for all of user's own groups and channels. 2024-04-08 17:02:52 +03:00
23rd 47bf099b88 Fixed updating of field placeholder in compose controls while editing. 2024-04-08 06:55:44 +03:00
23rd 94f1d23788 Fixed behavior to open section with scheduled messages at top. 2024-04-08 04:12:14 +03:00
Ilya Fedin 84ce72ec7a Fix a crash due to half-hidden media viewer 2024-04-07 14:28:51 +04:00
Ilya Fedin 3da8351522 Let Wayland to use QGuiApplication::screenAt (forgotten place) 2024-04-07 14:08:40 +04:00
Ilya Fedin 542153d950 Use nasm from repository 2024-04-07 11:20:46 +04:00
Ilya Fedin 090fdfb458 Add asan libraries to Docker image 2024-04-07 11:20:46 +04:00
John Preston 77835a43a5 Version 4.16.4: Update patches on Linux. 2024-04-07 11:19:23 +04:00
John Preston 1a2a1f1c17 Version 4.16.4.
- Bug fixes and other minor improvements.
2024-04-06 22:59:03 +04:00
John Preston eaaa704fa4 Check the URL in IV like in attach bots. 2024-04-06 22:59:03 +04:00
John Preston 7803f8e670 Simplify escaping when parsing IV. 2024-04-06 22:59:03 +04:00
Sergey A. Osokin f36e3c213e Fix build on FreeBSD 13.3 / llvm 17.0.6 / qt 5.15.13 2024-04-06 20:30:08 +04:00
John Preston 6fb1e23ed5 Fix file dialog filter for videos from attach menu. 2024-04-06 13:05:12 +04:00
John Preston 86d0c49e44 Add "Boost Group/Channel" button to chat menu. 2024-04-06 13:05:12 +04:00
John Preston 9251e6faba Use better title in boost box. 2024-04-06 13:05:12 +04:00
John Preston 8f8725e1af Beta version 4.16.3: Fix dav1d in FFmpeg on macOS. 2024-04-05 21:25:20 +04:00
John Preston 0ce6a4cbdb Beta version 4.16.3: Re-enable system proxy (Linux).
This reverts commit 1e6fb202f0.
2024-04-05 20:48:06 +04:00
John Preston ad3f705f50 Beta version 4.16.3.
- Improve media upload speed.
- Update FFmpeg to 6.1.1.
2024-04-05 15:35:01 +04:00
John Preston c5847caa91 Update FFmpeg to 6.1.1: Fix AV1 videos. 2024-04-05 14:42:29 +04:00
John Preston 8df6d9db7e Don't update server-time too frequently. 2024-04-05 09:51:20 +04:00
John Preston a9c1970f41 Send up to 1MB of parts to a single session. 2024-04-05 09:51:20 +04:00
John Preston c3f0d2ef31 Adaptive upload up to 8 sessions. 2024-04-05 09:51:20 +04:00
John Preston 0dcc439dda Allow upload requests for several files at once. 2024-04-05 09:51:20 +04:00
John Preston 5b0cac47ad Reapply "Use plain vector for prepared upload parts."
This reverts commit f6f8eefaa0.
2024-04-05 09:51:20 +04:00
John Preston b39e78a4a9 Reapply "Remove SendMediaReady legacy helper."
This reverts commit 09f07a7a9d.
2024-04-05 09:51:20 +04:00
John Preston 690d52f7bc Version 4.16.2.
- Use IV by default for Telegraph and some Telegram links.
- Support IV links in bot web-apps.
- Some bug fixes.
2024-04-04 21:13:00 +04:00
John Preston 23883ed4a1 Use generic way for FAQ links. 2024-04-04 21:08:56 +04:00
John Preston ea178862d8 Open some telegram.org and Telegram links in IV. 2024-04-04 21:08:19 +04:00
John Preston 09f07a7a9d Revert "Remove SendMediaReady legacy helper."
This reverts commit 91f8989f70.
2024-04-04 18:36:07 +04:00
John Preston f6f8eefaa0 Revert "Use plain vector for prepared upload parts."
This reverts commit aaaeea2979.
2024-04-04 18:36:00 +04:00
John Preston ede6e18bc9 Fix QOI image reader. 2024-04-04 18:35:20 +04:00
John Preston 36cb28d5cf Respect 'try_instant_view' in webapps. 2024-04-04 18:35:20 +04:00
John Preston 9464f4b095 Fix collectible channel links. 2024-04-04 17:51:53 +04:00
23rd b31d43cbed Fixed circle drawing in titles of some sections in channel earn info. 2024-04-04 17:51:53 +04:00
23rd 2a388ae4b2 Improved FAQ buttons with opening link in instant view. 2024-04-04 17:51:53 +04:00
23rd d675e31a51 Fixed display of integer numbers in channel earn section. 2024-04-04 17:51:53 +04:00
23rd e32de38d04 Added url to learn more about monetization to langpack. 2024-04-04 17:51:53 +04:00
23rd 154753c732 Removed migrated groups from list of user's own groups. 2024-04-04 17:51:53 +04:00
Klemens Nanni 53b75c8ea4 update lib_base to include OpenBSD fix 2024-04-04 15:52:01 +04:00
Klemens Nanni 776e80b4d6 Fix tdesktop 4.15.6 build on OpenBSD
7.5-current with clang 16.0.6 and Qt6 fails, not entirely sure why...
2024-04-04 15:52:01 +04:00
Ilya Fedin b09cede008 Fix uploading artifact on Linux 2024-04-04 15:51:22 +04:00
Ilya Fedin e2a0483b9f Enable artifacts for GH actions 2024-04-04 15:51:22 +04:00
John Preston aaaeea2979 Use plain vector for prepared upload parts. 2024-04-03 12:39:08 +04:00
John Preston 91f8989f70 Remove SendMediaReady legacy helper. 2024-04-03 11:59:33 +04:00
John Preston ae36019ba9 Version 4.16.1.
- Show information about Fragment phone numbers and usernames.
- Fix jump to original story from a story repost.
- Fix old image display in viewer in some cases.
- Fix several crashes.
2024-04-02 23:13:05 +04:00
John Preston 1e0002aa74 Fix jump to original from story repost. 2024-04-02 23:09:26 +04:00
John Preston 1061fb6c85 Implement collectible username / phone info boxes. 2024-04-02 22:56:21 +04:00
John Preston 22f504ca21 Add hidden buttons to langpack. 2024-04-02 22:56:05 +04:00
John Preston a74c5ee719 Fix complex-shaped Ui::Text::String geometry. 2024-04-02 22:56:05 +04:00
John Preston ef04ed447f Fix 'listening' state show in group video chats.
Regression was introduced in c3ca8c6258.
2024-04-02 19:22:30 +04:00
Ilya Fedin c678973119 Update patches on Linux 2024-04-02 17:40:41 +04:00
Ilya Fedin 587b07a648 Update Qt to 6.7.0 on Linux 2024-04-02 17:40:41 +04:00
John Preston 7fa3c6f8e8 Return media viewer hiding glitch workaround. 2024-04-02 13:19:22 +04:00
John Preston 9957678fb7 Fix adding from "Emoji from this message". 2024-04-02 13:15:03 +04:00
John Preston 971803803c Fix ripple animation on Added sticker set button. 2024-04-02 12:47:24 +04:00
John Preston 8ab118a8e9 Fix rare crashes in message sending animations. 2024-04-02 12:20:40 +04:00
John Preston 1da9df690f Fix memory leak in downloads thumbnail loading. 2024-04-02 12:20:40 +04:00
John Preston 615ad85d26 Fix possible crash in notifications setup.
Initial _account assignment triggered sync createManager(),
which in case of native Windows notifications called
ToastNotificationManager::CreateToastNotifier, which could enter
qt-wndproc-message processing with QEvent::ApplicationActivated
delivery and calling updateNonIdle() which called
Window::Controller::account(), that wasn't yet set.
2024-04-02 12:20:40 +04:00
John Preston e02b60d8fa Fix placeholder in chat intro setup. 2024-04-02 12:20:40 +04:00
Ilya Fedin 3fc4030ca6 Migrate xz in Dockerfile to the URL used in prepare.py 2024-04-02 10:26:43 +04:00
739 changed files with 29466 additions and 28134 deletions
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
@@ -1,32 +1,11 @@
name: No Response
name: Can't reproduce.
# Both `issue_comment` and `scheduled` event types are required for this Action
# to work properly.
on:
issue_comment:
types: [created]
schedule:
- cron: '0 0 * * *'
- cron: '0 3 * * *'
jobs:
waiting-for-answer:
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/no-response@v0.5.0
with:
token: ${{ github.token }}
responseRequiredLabel: waiting for answer
needs-user-action:
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/no-response@v0.5.0
with:
token: ${{ github.token }}
responseRequiredLabel: needs user action
cant-reproduce:
if: github.event_name != 'issue_comment'
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/no-response@v0.5.0
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
submodules: recursive
@@ -31,7 +31,7 @@ jobs:
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
- name: Free up some disk space.
uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
- name: Docker image build.
run: |
+5 -6
View File
@@ -49,17 +49,16 @@ jobs:
defines:
- ""
- "DESKTOP_APP_DISABLE_X11_INTEGRATION"
- "DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION"
env:
UPLOAD_ARTIFACT: "false"
UPLOAD_ARTIFACT: "true"
steps:
- name: Get repository name.
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.REPO_NAME }}
@@ -115,9 +114,9 @@ jobs:
if: env.UPLOAD_ARTIFACT == 'true'
run: |
cd $REPO_NAME/out/Debug
mkdir artifact
mv {Telegram,Updater} artifact/
- uses: actions/upload-artifact@master
sudo mkdir artifact
sudo mv {Telegram,Updater} artifact/
- uses: actions/upload-artifact@v4
if: env.UPLOAD_ARTIFACT == 'true'
name: Upload artifact.
with:
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v3
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: 45
+5 -5
View File
@@ -47,7 +47,7 @@ jobs:
defines:
- ""
env:
UPLOAD_ARTIFACT: "false"
UPLOAD_ARTIFACT: "true"
ONLY_CACHE: "false"
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
@@ -56,7 +56,7 @@ jobs:
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.REPO_NAME }}
@@ -76,7 +76,7 @@ jobs:
- name: ThirdParty cache.
id: cache-third-party
uses: actions/cache@v3.0.11
uses: actions/cache@v4
with:
path: ThirdParty
key: ${{ runner.OS }}-third-party-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
@@ -84,7 +84,7 @@ jobs:
- name: Libraries cache.
id: cache-libs
uses: actions/cache@v3.0.11
uses: actions/cache@v4
with:
path: Libraries
key: ${{ runner.OS }}-libs-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
@@ -134,7 +134,7 @@ jobs:
mkdir artifact
mv Telegram.app artifact/
mv Updater artifact/
- uses: actions/upload-artifact@master
- uses: actions/upload-artifact@v4
if: env.UPLOAD_ARTIFACT == 'true'
name: Upload artifact.
with:
+6 -6
View File
@@ -49,8 +49,8 @@ jobs:
env:
GIT: "https://github.com"
OPENALDIR: "/usr/local/opt/openal-soft"
UPLOAD_ARTIFACT: "false"
CMAKE_PREFIX_PATH: "/usr/local/opt/ffmpeg@6:/usr/local/opt/openal-soft"
UPLOAD_ARTIFACT: "true"
ONLY_CACHE: "false"
MANUAL_CACHING: "1"
AUTO_CACHING: "1"
@@ -60,7 +60,7 @@ jobs:
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.REPO_NAME }}
@@ -69,7 +69,7 @@ jobs:
run: |
brew update
brew upgrade || true
brew install autoconf automake boost cmake ffmpeg openal-soft openssl opus ninja pkg-config python qt yasm xz
brew install autoconf automake boost cmake ffmpeg@6 openal-soft openssl opus ninja pkg-config python qt yasm xz
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcodebuild -version > CACHE_KEY.txt
@@ -99,7 +99,7 @@ jobs:
- name: WebRTC cache.
id: cache-webrtc
uses: actions/cache@v3.0.11
uses: actions/cache@v4
with:
path: ${{ env.LibrariesPath }}/tg_owt
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_owt-version.json') }}
@@ -153,7 +153,7 @@ jobs:
cd $REPO_NAME/build
mkdir artifact
mv Telegram.dmg artifact/
- uses: actions/upload-artifact@master
- uses: actions/upload-artifact@v4
if: env.UPLOAD_ARTIFACT == 'true'
name: Upload artifact.
with:
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
SKIP: "0"
to_branch: "master"
steps:
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@v4
with:
fetch-depth: 0
if: env.SKIP == '0'
+16
View File
@@ -0,0 +1,16 @@
name: Needs user action.
on:
issue_comment:
types: [created]
schedule:
- cron: '0 2 * * *'
jobs:
needs-user-action:
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/no-response@v0.5.0
with:
token: ${{ github.token }}
responseRequiredLabel: needs user action
+5 -5
View File
@@ -43,11 +43,11 @@ jobs:
runs-on: ubuntu-20.04
env:
UPLOAD_ARTIFACT: "false"
UPLOAD_ARTIFACT: "true"
steps:
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
@@ -61,10 +61,10 @@ jobs:
sudo snap run lxd waitready
- name: Free up some disk space.
uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
- name: Telegram Desktop snap build.
run: sg lxd -c 'snap run snapcraft -v'
run: sg lxd -c 'snap run snapcraft --verbosity=debug'
- name: Move artifact.
if: env.UPLOAD_ARTIFACT == 'true'
@@ -75,7 +75,7 @@ jobs:
mkdir artifact
mv $artifact_name artifact
- uses: actions/upload-artifact@master
- uses: actions/upload-artifact@v4
if: env.UPLOAD_ARTIFACT == 'true'
name: Upload artifact.
with:
+1 -1
View File
@@ -7,7 +7,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v5
- uses: actions/stale@v9
with:
stale-issue-message: |
Hey there!
+16
View File
@@ -0,0 +1,16 @@
name: Waiting for answer.
on:
issue_comment:
types: [created]
schedule:
- cron: '30 0 * * *'
jobs:
waiting-for-answer:
runs-on: ubuntu-latest
steps:
- uses: lee-dohm/no-response@v0.5.0
with:
token: ${{ github.token }}
responseRequiredLabel: waiting for answer
+5 -5
View File
@@ -50,7 +50,7 @@ jobs:
generator: ["", "Ninja Multi-Config"]
env:
UPLOAD_ARTIFACT: "false"
UPLOAD_ARTIFACT: "true"
ONLY_CACHE: "false"
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
@@ -69,13 +69,13 @@ jobs:
shell: bash
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- uses: ilammy/msvc-dev-cmd@v1.12.0
- uses: ilammy/msvc-dev-cmd@v1.13.0
name: Native Tools Command Prompt.
with:
arch: ${{ matrix.arch }}
- name: Clone.
uses: actions/checkout@v3.1.0
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}
@@ -96,7 +96,7 @@ jobs:
- name: Libraries cache.
id: cache-libs
uses: actions/cache@v3.0.11
uses: actions/cache@v4
with:
path: ${{ env.TBUILD }}\Libraries
key: ${{ runner.OS }}-${{ matrix.arch }}-libs-${{ env.CACHE_KEY }}
@@ -183,7 +183,7 @@ jobs:
mkdir artifact
move %OUT%\Telegram.exe artifact/
move %OUT%\Updater.exe artifact/
- uses: actions/upload-artifact@master
- uses: actions/upload-artifact@v4
name: Upload artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
with:
+1
View File
@@ -18,6 +18,7 @@ Release/
*.xcodeproj
ipch/
.vs/
.vscode/
/Telegram/log.txt
/Telegram/data
+3 -9
View File
@@ -76,15 +76,12 @@
[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
[submodule "Telegram/ThirdParty/plasma-wayland-protocols"]
path = Telegram/ThirdParty/plasma-wayland-protocols
url = https://github.com/KDE/plasma-wayland-protocols.git
[submodule "Telegram/ThirdParty/wayland-protocols"]
path = Telegram/ThirdParty/wayland-protocols
url = https://github.com/gitlab-freedesktop-mirrors/wayland-protocols.git
[submodule "Telegram/ThirdParty/kimageformats"]
path = Telegram/ThirdParty/kimageformats
url = https://github.com/KDE/kimageformats.git
@@ -94,9 +91,6 @@
[submodule "Telegram/ThirdParty/cld3"]
path = Telegram/ThirdParty/cld3
url = https://github.com/google/cld3.git
[submodule "Telegram/ThirdParty/wayland"]
path = Telegram/ThirdParty/wayland
url = https://github.com/gitlab-freedesktop-mirrors/wayland.git
[submodule "Telegram/ThirdParty/libprisma"]
path = Telegram/ThirdParty/libprisma
url = https://github.com/desktop-app/libprisma.git
+1 -1
View File
@@ -62,7 +62,7 @@ if (NOT DESKTOP_APP_USE_PACKAGED)
if (WIN32)
set(qt_version 5.15.13)
elseif (APPLE)
set(qt_version 6.2.7)
set(qt_version 6.2.8)
endif()
endif()
include(cmake/external/qt/package.cmake)
+54 -48
View File
@@ -132,8 +132,6 @@ set(ayugram_files
ayu/ui/sections/edited/edited_log_item.h
ayu/ui/sections/edited/edited_log_section.cpp
ayu/ui/sections/edited/edited_log_section.h
ayu/ui/boxes/server_read_confirmation_box.cpp
ayu/ui/boxes/server_read_confirmation_box.h
ayu/ui/boxes/edit_deleted_mark.cpp
ayu/ui/boxes/edit_deleted_mark.h
ayu/ui/boxes/edit_edited_mark.cpp
@@ -191,6 +189,8 @@ PRIVATE
api/api_common.h
api/api_confirm_phone.cpp
api/api_confirm_phone.h
api/api_credits.cpp
api/api_credits.h
api/api_earn.cpp
api/api_earn.h
api/api_editing.cpp
@@ -344,6 +344,8 @@ PRIVATE
boxes/local_storage_box.h
boxes/max_invite_box.cpp
boxes/max_invite_box.h
boxes/moderate_messages_box.cpp
boxes/moderate_messages_box.h
boxes/peer_list_box.cpp
boxes/peer_list_box.h
boxes/peer_list_controllers.cpp
@@ -368,6 +370,8 @@ PRIVATE
boxes/ringtones_box.h
boxes/self_destruction_box.cpp
boxes/self_destruction_box.h
boxes/send_credits_box.cpp
boxes/send_credits_box.h
boxes/send_files_box.cpp
boxes/send_files_box.h
boxes/sessions_box.cpp
@@ -510,6 +514,8 @@ PRIVATE
core/launcher.h
core/local_url_handlers.cpp
core/local_url_handlers.h
core/phone_click_handler.cpp
core/phone_click_handler.h
core/sandbox.cpp
core/sandbox.h
core/shortcuts.cpp
@@ -531,6 +537,16 @@ PRIVATE
data/business/data_business_info.h
data/business/data_shortcut_messages.cpp
data/business/data_shortcut_messages.h
data/components/factchecks.cpp
data/components/factchecks.h
data/components/recent_peers.cpp
data/components/recent_peers.h
data/components/scheduled_messages.cpp
data/components/scheduled_messages.h
data/components/sponsored_messages.cpp
data/components/sponsored_messages.h
data/components/top_peers.cpp
data/components/top_peers.h
data/notify/data_notify_settings.cpp
data/notify/data_notify_settings.h
data/notify/data_peer_notify_settings.cpp
@@ -600,6 +616,8 @@ PRIVATE
data/data_groups.h
data/data_histories.cpp
data/data_histories.h
data/data_history_messages.cpp
data/data_history_messages.h
data/data_lastseen_status.h
data/data_location.cpp
data/data_location.h
@@ -648,14 +666,10 @@ PRIVATE
data/data_send_action.h
data/data_session.cpp
data/data_session.h
data/data_scheduled_messages.cpp
data/data_scheduled_messages.h
data/data_shared_media.cpp
data/data_shared_media.h
data/data_sparse_ids.cpp
data/data_sparse_ids.h
data/data_sponsored_messages.cpp
data/data_sponsored_messages.h
data/data_statistics.h
data/data_stories.cpp
data/data_stories.h
@@ -679,6 +693,18 @@ PRIVATE
data/data_wall_paper.h
data/data_web_page.cpp
data/data_web_page.h
dialogs/ui/dialogs_layout.cpp
dialogs/ui/dialogs_layout.h
dialogs/ui/dialogs_message_view.cpp
dialogs/ui/dialogs_message_view.h
dialogs/ui/dialogs_stories_content.cpp
dialogs/ui/dialogs_stories_content.h
dialogs/ui/dialogs_suggestions.cpp
dialogs/ui/dialogs_suggestions.h
dialogs/ui/dialogs_topics_view.cpp
dialogs/ui/dialogs_topics_view.h
dialogs/ui/dialogs_video_userpic.cpp
dialogs/ui/dialogs_video_userpic.h
dialogs/dialogs_entry.cpp
dialogs/dialogs_entry.h
dialogs/dialogs_indexed_list.cpp
@@ -701,16 +727,6 @@ PRIVATE
dialogs/dialogs_search_tags.h
dialogs/dialogs_widget.cpp
dialogs/dialogs_widget.h
dialogs/ui/dialogs_layout.cpp
dialogs/ui/dialogs_layout.h
dialogs/ui/dialogs_message_view.cpp
dialogs/ui/dialogs_message_view.h
dialogs/ui/dialogs_stories_content.cpp
dialogs/ui/dialogs_stories_content.h
dialogs/ui/dialogs_topics_view.cpp
dialogs/ui/dialogs_topics_view.h
dialogs/ui/dialogs_video_userpic.cpp
dialogs/ui/dialogs_video_userpic.h
editor/color_picker.cpp
editor/color_picker.h
editor/controllers/controllers.h
@@ -751,6 +767,8 @@ PRIVATE
history/view/controls/compose_controls_common.h
history/view/controls/history_view_compose_controls.cpp
history/view/controls/history_view_compose_controls.h
history/view/controls/history_view_compose_media_edit_manager.cpp
history/view/controls/history_view_compose_media_edit_manager.h
history/view/controls/history_view_compose_search.cpp
history/view/controls/history_view_compose_search.h
history/view/controls/history_view_draft_options.cpp
@@ -842,6 +860,8 @@ PRIVATE
history/view/history_view_about_view.h
history/view/history_view_bottom_info.cpp
history/view/history_view_bottom_info.h
history/view/history_view_chat_preview.cpp
history/view/history_view_chat_preview.h
history/view/history_view_contact_status.cpp
history/view/history_view_contact_status.h
history/view/history_view_context_menu.cpp
@@ -856,6 +876,8 @@ PRIVATE
history/view/history_view_emoji_interactions.h
history/view/history_view_empty_list_bubble.cpp
history/view/history_view_empty_list_bubble.h
history/view/history_view_fake_items.cpp
history/view/history_view_fake_items.h
history/view/history_view_group_call_bar.cpp
history/view/history_view_group_call_bar.h
history/view/history_view_item_preview.h
@@ -886,14 +908,14 @@ PRIVATE
history/view/history_view_send_action.h
history/view/history_view_service_message.cpp
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_sublist_section.cpp
history/view/history_view_sublist_section.h
history/view/history_view_text_helper.cpp
history/view/history_view_text_helper.h
history/view/history_view_transcribe_button.cpp
history/view/history_view_transcribe_button.h
history/view/history_view_translate_bar.cpp
@@ -1270,11 +1292,8 @@ PRIVATE
payments/payments_checkout_process.h
payments/payments_form.cpp
payments/payments_form.h
platform/linux/linux_wayland_integration_dummy.cpp
platform/linux/linux_wayland_integration.cpp
platform/linux/linux_wayland_integration.h
platform/linux/linux_xdp_open_with_dialog.cpp
platform/linux/linux_xdp_open_with_dialog.h
payments/payments_non_panel_process.cpp
payments/payments_non_panel_process.h
platform/linux/file_utilities_linux.cpp
platform/linux/file_utilities_linux.h
platform/linux/launcher_linux.cpp
@@ -1420,6 +1439,10 @@ PRIVATE
settings/settings_codes.h
settings/settings_common_session.cpp
settings/settings_common_session.h
settings/settings_credits.cpp
settings/settings_credits.h
settings/settings_credits_graphics.cpp
settings/settings_credits_graphics.h
settings/settings_experimental.cpp
settings/settings_experimental.h
settings/settings_folders.cpp
@@ -1515,6 +1538,8 @@ PRIVATE
ui/controls/silent_toggle.h
ui/controls/userpic_button.cpp
ui/controls/userpic_button.h
ui/effects/credits_graphics.cpp
ui/effects/credits_graphics.h
ui/effects/emoji_fly_animation.cpp
ui/effects/emoji_fly_animation.h
ui/effects/message_sending_animation_common.h
@@ -1530,8 +1555,6 @@ PRIVATE
ui/image/image_location.h
ui/image/image_location_factory.cpp
ui/image/image_location_factory.h
ui/widgets/level_meter.cpp
ui/widgets/level_meter.h
ui/countryinput.cpp
ui/countryinput.h
ui/dynamic_thumbnails.cpp
@@ -1547,6 +1570,8 @@ PRIVATE
ui/search_field_controller.h
ui/text/format_song_document_name.cpp
ui/text/format_song_document_name.h
ui/widgets/label_with_custom_emoji.cpp
ui/widgets/label_with_custom_emoji.h
ui/unread_badge.cpp
ui/unread_badge.h
window/main_window.cpp
@@ -1562,6 +1587,8 @@ PRIVATE
window/section_widget.h
window/window_adaptive.cpp
window/window_adaptive.h
window/window_chat_preview.cpp
window/window_chat_preview.h
window/window_connecting_widget.cpp
window/window_connecting_widget.h
window/window_controller.cpp
@@ -1574,6 +1601,8 @@ PRIVATE
window/window_lock_widgets.h
window/window_main_menu.cpp
window/window_main_menu.h
window/window_main_menu_helpers.cpp
window/window_main_menu_helpers.h
window/window_media_preview.cpp
window/window_media_preview.h
window/window_peer_menu.cpp
@@ -1625,16 +1654,6 @@ if (NOT build_winstore)
)
endif()
if (DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION)
remove_target_sources(Telegram ${src_loc}
platform/linux/linux_wayland_integration.cpp
)
else()
remove_target_sources(Telegram ${src_loc}
platform/linux/linux_wayland_integration_dummy.cpp
)
endif()
if (DESKTOP_APP_USE_PACKAGED)
remove_target_sources(Telegram ${src_loc}
platform/mac/mac_iconv_helper.c
@@ -1774,19 +1793,6 @@ else()
desktop-app::external_xcb
)
endif()
if (NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION)
qt_generate_wayland_protocol_client_sources(Telegram
FILES
${third_party_loc}/wayland/protocol/wayland.xml
${third_party_loc}/plasma-wayland-protocols/src/protocols/plasma-shell.xml
)
target_link_libraries(Telegram
PRIVATE
desktop-app::external_wayland_client
)
endif()
endif()
if (build_macstore)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+30 -1
View File
@@ -134,9 +134,32 @@ html.custom_scroll ::-webkit-scrollbar-thumb:hover {
.page-slide {
position: relative;
width: 100%;
min-height: 100%;
margin-left: 0%;
transition: margin 240ms ease-in-out;
}
.page-footer {
height: 32px;
margin-top: -32px;
background: var(--td-window-bg-over);
}
.page-footer .content {
padding: 3px 18px;
font-size: 15px;
color: var(--td-window-sub-text-fg);
text-align: center;
}
.page-footer .wrong {
position: relative;
padding: 5px;
margin: -5px;
color: var(--td-window-sub-text-fg);
text-decoration: none;
cursor: pointer;
}
.page-footer .wrong:hover {
text-decoration: underline;
}
.hidden-left,
.hidden-right {
pointer-events: none;
@@ -148,7 +171,7 @@ html.custom_scroll ::-webkit-scrollbar-thumb:hover {
margin-left: 100%;
}
article {
padding-bottom: 12px;
padding-bottom: 40px;
overflow-y: hidden;
overflow-x: auto;
white-space: pre-wrap;
@@ -893,6 +916,9 @@ section.related a.related-link:after {
right: 0;
bottom: 0;
}
section.related a.related-link:last-child:after {
border-bottom: 0px;
}
section.related .related-link-url {
display: block;
font-size: 15px;
@@ -1027,6 +1053,9 @@ section.channel > a > h4 {
display: block;
margin: 0 auto;
}
.media-outer {
margin-bottom: 16px;
}
.photo-wrap,
.video-wrap {
width: 100%;
+9 -7
View File
@@ -26,7 +26,7 @@ var IV = {
}
target = target.parentNode;
}
if (!target || !target.hasAttribute('href')) {
if (!target || (context === '' && !target.hasAttribute('href'))) {
return;
}
var base = document.createElement('A');
@@ -413,9 +413,12 @@ var IV = {
var article = function (el) {
return el.getElementsByTagName('article')[0];
};
var from = article(IV.findPageScroll());
var to = article(IV.makeScrolledContent(data.html));
morphdom(from, to, {
var footer = function (el) {
return el.getElementsByClassName('page-footer')[0];
};
var from = IV.findPageScroll();
var to = IV.makeScrolledContent(data.html);
morphdom(article(from), article(to), {
onBeforeElUpdated: function (fromEl, toEl) {
if (fromEl.classList.contains('video')
&& toEl.classList.contains('video')
@@ -439,6 +442,7 @@ var IV = {
return !fromEl.isEqualNode(toEl);
}
});
morphdom(footer(from), footer(to));
IV.initMedia();
eval(data.js);
},
@@ -477,9 +481,7 @@ var IV = {
var result = document.createElement('div');
result.className = 'page-scroll';
result.tabIndex = '-1';
result.innerHTML = '<div class="page-slide"><article>'
+ html
+ '</article></div>';
result.innerHTML = html.trim();
result.onscroll = IV.frameScrolled;
return result;
},
+191 -2
View File
@@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_menu_set_status" = "Set Emoji Status";
"lng_menu_change_status" = "Change Emoji Status";
"lng_menu_my_stories" = "My Stories";
"lng_menu_my_groups" = "My Groups";
"lng_menu_my_channels" = "My Channels";
"lng_disable_notifications_from_tray" = "Disable notifications";
"lng_enable_notifications_from_tray" = "Enable notifications";
@@ -249,6 +251,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_caption_limit2#other" = "Make the caption shorter or subscribe to **Telegram Premium** to double the limit to **{count}** characters.";
"lng_caption_limit_reached#one" = "You've reached the media caption limit. Please make the caption shorter by {count} character.";
"lng_caption_limit_reached#other" = "You've reached the media caption limit. Please make the caption shorter by {count} characters.";
"lng_caption_move_up" = "Move Caption Up";
"lng_caption_move_down" = "Move Caption Down";
"lng_file_size_limit_title" = "File Too Large";
"lng_file_size_limit#one" = "{count} Gb";
@@ -300,6 +304,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sure_ban_admin" = "This user is an admin. Are you sure you want to go ahead and restrict them?";
"lng_sure_enable_socks" = "Are you sure you want to enable this proxy?\n\nServer: {server}\nPort: {port}\n\nYou can change your proxy server later in the Settings (Connection Type).";
"lng_sure_enable" = "Enable";
"lng_proxy_box_title" = "Enable proxy";
"lng_proxy_box_server" = "Server";
"lng_proxy_box_port" = "Port";
"lng_proxy_box_secret" = "Secret";
"lng_proxy_box_status" = "Status";
"lng_proxy_box_username" = "Username";
"lng_proxy_box_password" = "Password";
"lng_proxy_invalid" = "The proxy link is invalid.";
"lng_proxy_unsupported" = "Your Telegram Desktop version doesn't support this proxy type or the proxy link is invalid. Please update Telegram Desktop to the latest version.";
@@ -307,7 +318,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_limit_reached#one" = "You've reached the message text limit. Please make the text shorter by {count} character.";
"lng_edit_limit_reached#other" = "You've reached the message text limit. Please make the text shorter by {count} characters.";
"lng_edit_message" = "Edit message";
"lng_edit_message_text" = "New message text...";
"lng_edit_message_text" = "Caption";
"lng_deleted" = "Deleted Account";
"lng_deleted_message" = "Deleted message";
"lng_deleted_story" = "Deleted story";
@@ -469,6 +480,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_bio_placeholder" = "Bio";
"lng_collectible_username_title" = "{username} is a collectible username that belongs to";
"lng_collectible_username_info" = "This username was bought on **Fragment** on {date} for {price}";
"lng_collectible_username_copy" = "Copy Link";
"lng_collectible_phone_title" = "{phone} is a collectible phone number that belongs to";
"lng_collectible_phone_info" = "This phone number was bought on **Fragment** on {date} for {price}";
"lng_collectible_phone_copy" = "Copy Phone Number";
"lng_collectible_learn_more" = "Learn More";
"lng_settings_section_info" = "My info";
"lng_settings_section_notify" = "Notifications";
@@ -551,6 +570,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_reaction_invoice" = "{reaction} to your invoice";
"lng_reaction_gif" = "{reaction} to your GIF";
"lng_effect_add_title" = "Add an animated effect";
"lng_effect_stickers_title" = "Effects from stickers";
"lng_effect_send" = "Send with Effect";
"lng_effect_none" = "No effects found.";
"lng_effect_premium" = "Subscribe to {link} to add this animated effect.";
"lng_effect_premium_link" = "Telegram Premium";
"lng_languages" = "Languages";
"lng_languages_none" = "No languages found.";
"lng_languages_count#one" = "{count} language";
@@ -720,10 +746,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_angle_backend_d3d11on12" = "D3D11on12";
"lng_settings_angle_backend_opengl" = "OpenGL";
"lng_settings_angle_backend_disabled" = "Disabled";
"lng_settings_top_peers_title" = "Frequent contacts";
"lng_settings_top_peers_suggest" = "Suggest frequent contacts";
"lng_settings_top_peers_about" = "Display people you message frequently at the top of the search section for quick access.";
"lng_settings_sensitive_title" = "Sensitive content";
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
"lng_settings_security_bots" = "Bots and websites";
"lng_settings_file_confirmations" = "File open confirmations";
"lng_settings_edit_extensions" = "Extensions whitelist";
"lng_settings_edit_extensions_about" = "Open files with the following extensions without additional confirmation.";
"lng_settings_edit_ip_confirm" = "IP reveal warning";
"lng_settings_edit_ip_confirm_about" = "Show confirmation when opening files that may reveal your IP address.";
"lng_settings_clear_payment_info" = "Clear Payment and Shipping Info";
"lng_settings_logged_in" = "Connected websites";
"lng_settings_logged_in_title" = "Logged in with Telegram";
@@ -751,6 +785,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_power_chat" = "Animations in Chats";
"lng_settings_power_chat_background" = "Background rotation";
"lng_settings_power_chat_spoiler" = "Animated spoiler effect";
"lng_settings_power_chat_effects" = "Effects in messages";
"lng_settings_power_calls" = "Animations in Calls";
"lng_settings_power_ui" = "Interface animations";
"lng_settings_power_auto" = "Save Power on Low Battery";
@@ -825,6 +860,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_auto_night_mode_on" = "System";
"lng_settings_auto_night_warning" = "You have enabled auto-night mode. If you want to change the dark mode settings, you'll need to disable it first.";
"lng_settings_auto_night_disable" = "Disable";
"lng_settings_font_family" = "Font family";
"lng_settings_color_title" = "Color preview";
"lng_settings_color_reply" = "Reply to your message";
@@ -1034,6 +1070,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_proxy_sponsor" = "Proxy sponsor";
"lng_proxy_sponsor_about" = "This channel is shown by your proxy server.\nTo remove this channel from your chats list,\ndisable the proxy in Telegram Settings.";
"lng_proxy_sponsor_warning" = "This proxy may display a sponsored channel in your chat list. This doesn't reveal any of your Telegram traffic.";
"lng_proxy_add_from_clipboard" = "Add proxy from clipboard";
"lng_proxy_add_from_clipboard_good_toast" = "Proxy was added from clipboard.";
"lng_proxy_add_from_clipboard_failed_toast" = "This is not a proxy link.";
"lng_proxy_add_from_clipboard_existing_toast" = "This proxy is already in the list.";
"lng_badge_psa_default" = "PSA";
"lng_about_psa_default" = "This message provides you with a public service announcement. To remove it from your chats list, right click it and select **Hide**.";
"lng_tooltip_psa_default" = "This message provides you with a public service announcement.";
@@ -1058,6 +1098,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_faq_button" = "Go to FAQ";
"lng_settings_ask_ok" = "Ask a Volunteer";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_faq_link" = "https://telegram.org/faq#general-questions";
"lng_settings_features" = "Telegram Features";
"lng_settings_logout" = "Log Out";
"lng_sure_logout" = "Are you sure you want to log out?";
@@ -1476,6 +1517,7 @@ 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_available_ph" = "Add 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.";
@@ -1484,6 +1526,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_reactions_boost_link" = "here";
"lng_manage_peer_reactions_limit" = "Channels can't have more custom reactions.";
"lng_manage_peer_reactions_max_title" = "Maximum number of reactions";
"lng_manage_peer_reactions_max_slider#one" = "{count} reaction per post";
"lng_manage_peer_reactions_max_slider#other" = "{count} reactions per post";
"lng_manage_peer_reactions_max_about" = "Limit the number of different reactions that can be added to a post, including already published ones.";
"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.";
"lng_manage_peer_antispam_not_enough#one" = "Aggressive filtering can be enabled only in groups with more than **{count} member**.";
@@ -1496,8 +1543,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_link_invite" = "Invite link";
"lng_manage_peer_link_expired" = "Expired link";
"lng_manage_private_group_title" = "Private";
"lng_manage_private_group_noforwards_title" = "Private restricted";
"lng_manage_public_group_title" = "Public";
"lng_manage_private_peer_title" = "Private";
"lng_manage_private_peer_noforwards_title" = "Private restricted";
"lng_manage_public_peer_title" = "Public";
"lng_manage_peer_send_title" = "Who can send new messages?";
"lng_manage_peer_send_only_members" = "Only members";
@@ -2253,6 +2302,43 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_business_about_chat_intro" = "Customize the message people see before they start a chat with you.";
"lng_business_subtitle_chat_links" = "Links to Chat";
"lng_business_about_chat_links" = "Create links that start a chat with you, suggesting the first message.";
"lng_business_subtitle_sponsored" = "Ads in Channels";
"lng_business_button_sponsored" = "Do Not Hide Ads";
"lng_business_about_sponsored" = "As a Premium subscriber, you dont see any ads on Telegram, but you can turn them on, for example, to view your own ads that you launched on the {link}";
"lng_business_about_sponsored_link" = "Telegram Ad Platform {emoji}";
"lng_business_about_sponsored_url" = "https://ads.telegram.org";
"lng_credits_summary_title" = "Telegram Stars";
"lng_credits_summary_about" = "Buy Stars to unlock content and services in miniapps on Telegram.";
"lng_credits_summary_options_subtitle" = "Choose package";
"lng_credits_summary_options_credits#one" = "{count} Star";
"lng_credits_summary_options_credits#other" = "{count} Stars";
"lng_credits_summary_options_more" = "More Options";
"lng_credits_summary_options_about" = "By proceeding and purchasing Stars, you agree with the {link}.";
"lng_credits_summary_options_about_link" = "Terms and Conditions";
"lng_credits_summary_history_tab_full" = "All Transactions";
"lng_credits_summary_history_tab_in" = "Incoming";
"lng_credits_summary_history_tab_out" = "Outgoing";
"lng_credits_summary_history_entry_inner_in" = "In-App Purchase";
"lng_credits_summary_balance" = "Balance";
"lng_credits_box_out_title" = "Confirm Your Purchase";
"lng_credits_box_out_sure#one" = "Do you want to buy **\"{text}\"** in **{bot}** for **{count} Star**?";
"lng_credits_box_out_sure#other" = "Do you want to buy **\"{text}\"** in **{bot}** for **{count} Stars**?";
"lng_credits_box_out_confirm#one" = "Confirm and Pay {emoji} {count} Star";
"lng_credits_box_out_confirm#other" = "Confirm and Pay {emoji} {count} Stars";
"lng_credits_box_out_about" = "Review the {link} for Stars.";
"lng_credits_summary_in_toast_title" = "Stars Acquired";
"lng_credits_summary_in_toast_about#one" = "**{count}** Star added to your balance.";
"lng_credits_summary_in_toast_about#other" = "**{count}** Stars added to your balance.";
"lng_credits_box_history_entry_peer" = "Recipient";
"lng_credits_box_history_entry_id" = "Transaction ID";
"lng_credits_box_history_entry_id_copied" = "Transaction ID copied to clipboard.";
"lng_credits_box_history_entry_about" = "You can dispute this transaction {link}.";
"lng_credits_box_history_entry_about_link" = "here";
"lng_credits_small_balance_title#one" = "{count} Star Needed";
"lng_credits_small_balance_title#other" = "{count} Stars Needed";
"lng_credits_small_balance_about" = "Buy **Stars** and use them on **{bot}** and other miniapps.";
"lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
"lng_location_title" = "Location";
"lng_location_about" = "Display the location of your business on your account.";
@@ -2823,7 +2909,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_in_dlg_audio_count#other" = "{count} audio";
"lng_ban_user" = "Ban User";
"lng_ban_users" = "Ban users";
"lng_restrict_users" = "Restrict users";
"lng_delete_all_from_user" = "Delete all from {user}";
"lng_delete_all_from_users" = "Delete all from users";
"lng_restrict_user_part" = "Partially restrict this user {emoji}";
"lng_restrict_users_part" = "Partially restrict users {emoji}";
"lng_restrict_user_full" = "Fully ban this user {emoji}";
"lng_restrict_users_full" = "Fully ban users {emoji}";
"lng_restrict_users_part_single_header" = "What can this user do?";
"lng_restrict_users_part_header#one" = "What can {count} selected user do?";
"lng_restrict_users_part_header#other" = "What can {count} selected users do?";
"lng_report_spam" = "Report Spam";
"lng_report_spam_and_leave" = "Report spam and leave";
"lng_report_spam_done" = "Thank you for your report.";
@@ -3051,6 +3147,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_unread_bar_some" = "Unread messages";
"lng_maps_point" = "Location";
"lng_live_location" = "Live Location";
"lng_live_location_now" = "updated just now";
"lng_live_location_minutes#one" = "updated {count} minute ago";
"lng_live_location_minutes#other" = "updated {count} minutes ago";
"lng_live_location_hours#one" = "updated {count} hour ago";
"lng_live_location_hours#other" = "updated {count} hours ago";
"lng_live_location_today" = "updated today at {time}";
"lng_live_location_yesterday" = "updated yesterday at {time}";
"lng_live_location_date_time" = "updated {date} at {time}";
"lng_save_photo" = "Save image";
"lng_save_video" = "Save video";
"lng_save_audio_file" = "Save audio file";
@@ -3127,6 +3232,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_reply_msg" = "Reply";
"lng_context_quote_and_reply" = "Quote & Reply";
"lng_context_edit_msg" = "Edit";
"lng_context_add_factcheck" = "Add Fact Check";
"lng_context_edit_factcheck" = "Edit Fact Check";
"lng_context_forward_msg" = "Forward Message";
"lng_context_send_now_msg" = "Send now";
"lng_context_reschedule" = "Reschedule";
@@ -3198,6 +3305,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_spoiler_effect" = "Hide with Spoiler";
"lng_context_disable_spoiler" = "Remove Spoiler";
"lng_factcheck_title" = "Fact Check";
"lng_factcheck_placeholder" = "Add Facts or Context";
"lng_factcheck_whats_this" = "what's this?";
"lng_factcheck_about" = "This clarification was provided by a fact checking agency assigned by the department of the government of your country ({country}) responsible for combatting misinformation.";
"lng_factcheck_add_done" = "Fact check added.";
"lng_factcheck_edit_done" = "Fact check edited.";
"lng_factcheck_remove_done" = "Fact check removed.";
"lng_factcheck_bottom" = "This clarification was provided by a fact checking agency assigned by the department of the government of your country ({country}) responsible for combatting misinformation.";
"lng_factcheck_links" = "Only **t.me/** links are allowed.";
"lng_translate_show_original" = "Show Original";
"lng_translate_bar_to" = "Translate to {name}";
"lng_translate_bar_to_other" = "Translate to {name}";
@@ -3318,6 +3435,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_add_contact" = "Create";
"lng_add_contact_button" = "New contact";
"lng_contacts_header" = "Contacts";
"lng_menu_not_contact" = "This number is not on Telegram";
"lng_contacts_hidden_stories" = "Hidden Stories";
"lng_contacts_stories_status#one" = "{count} story";
"lng_contacts_stories_status#other" = "{count} stories";
@@ -3394,6 +3512,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_mediaview_forward" = "Forward";
"lng_mediaview_delete" = "Delete";
"lng_mediaview_save_to_profile" = "Save to Profile";
"lng_mediaview_pin_story_done" = "Story pinned";
"lng_mediaview_pin_story_about" = "Now it will be always shown on the top.";
"lng_mediaview_pin_stories_done#one" = "{count} story pinned";
"lng_mediaview_pin_stories_done#other" = "{count} stories pinned";
"lng_mediaview_pin_stories_about#one" = "Now it will be always shown on the top.";
"lng_mediaview_pin_stories_about#other" = "Now they will be always shown on the top.";
"lng_mediaview_unpin_story_done" = "Story unpinned.";
"lng_mediaview_unpin_stories_done#one" = "{count} story unpinned";
"lng_mediaview_unpin_stories_done#other" = "{count} stories unpinned";
"lng_mediaview_pin_limit#one" = "You can't pin more than {count} story.";
"lng_mediaview_pin_limit#other" = "You can't pin more than {count} stories.";
"lng_mediaview_archive_story" = "Archive Story";
"lng_mediaview_photos_all" = "View all photos";
"lng_mediaview_files_all" = "View all files";
@@ -4469,10 +4598,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_translate_settings_about" = "The 'Translate' button will appear when you open a context menu on a text message.";
"lng_translate_settings_one" = "Please choose at least one language so that it can be used as the \"Translate to\" language.";
"lng_launch_exe_warning" = "This file has a {extension} extension.\nAre you sure you want to run it?";
"lng_launch_exe_warning" = "This file has {extension} extension.\nAre you sure you want to run it?";
"lng_launch_other_warning" = "This file has {extension} extension.\nAre you sure you want to open it?";
"lng_launch_svg_warning" = "Opening this file can potentially expose your IP address to its sender. Continue?";
"lng_launch_exe_sure" = "Run";
"lng_launch_other_sure" = "Open";
"lng_launch_exe_dont_ask" = "Don't ask me again";
"lng_launch_dont_ask" = "Remember for this file type";
"lng_launch_dont_ask_settings" = "You can later edit trusted file types in Settings > Privacy and Security > File open confirmations.";
"lng_polls_anonymous" = "Anonymous Poll";
"lng_polls_public" = "Poll";
@@ -4684,6 +4817,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_boost" = "Boost";
"lng_view_button_giftcode" = "Open";
"lng_view_button_iv" = "Instant View";
"lng_view_button_stickerset" = "View stickers";
"lng_view_button_emojipack" = "View emoji";
"lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?";
@@ -5040,6 +5175,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_earn_learn_coin_title" = "What is {emoji} TON?";
"lng_channel_earn_learn_coin_about" = "TON is a blockchain platform and cryptocurrency that Telegram uses for its high speed and low commissions on transactions. {link}";
"lng_channel_earn_learn_close" = "Got it";
"lng_channel_earn_learn_coin_link" = "https://telegram.org/blog/monetization-for-channels";
"lng_channel_earn_chart_top_hours" = "Ad impressions";
"lng_channel_earn_chart_revenue" = "Ad revenue";
"lng_channel_earn_chart_overriden_detail_currency" = "Revenue in TON";
@@ -5052,6 +5188,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_iv_share" = "Share";
"lng_iv_join_channel" = "Join";
"lng_iv_window_title" = "Instant View";
"lng_iv_wrong_layout" = "Wrong layout?";
"lng_limit_download_title" = "Download speed limited";
"lng_limit_download_subscribe" = "Subscribe to {link} and increase download speed {increase}.";
@@ -5066,6 +5203,58 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_limit_upload_increase_speed" = "by **{percent}**";
"lng_limit_upload_subscribe_link" = "Telegram Premium";
"lng_recent_frequent" = "Frequent contacts";
"lng_recent_frequent_all" = "Show all";
"lng_recent_frequent_collapse" = "Collapse";
"lng_recent_title" = "Recent";
"lng_recent_clear" = "Clear";
"lng_recent_clear_sure" = "Do you want to clear your search history?";
"lng_recent_remove" = "Remove from Recent";
"lng_recent_clear_all" = "Clear all";
"lng_recent_hide_top" = "Remove all & Disable";
"lng_recent_hide_sure" = "Are you sure you want to clear and disable frequent contacts list?\n\nYou can always turn this feature back on in Settings > Privacy > Suggest Frequent Contacts.";
"lng_recent_hide_button" = "Hide";
"lng_recent_none" = "Recent search results\nwill appear here.";
"lng_recent_chats" = "Chats";
"lng_recent_channels" = "Channels";
"lng_channels_none_title" = "No channels yet...";
"lng_channels_none_about" = "You are not currently subscribed to any channels.";
"lng_channels_your_title" = "Channels you joined";
"lng_channels_your_more" = "Show more";
"lng_channels_your_less" = "Show less";
"lng_channels_recommended" = "Recommended channels";
"lng_font_box_title" = "Choose font family";
"lng_font_default" = "Default";
"lng_font_system" = "System font";
"lng_font_not_found" = "Font not found.";
"lng_search_tab_my_messages" = "My Messages";
"lng_search_tab_this_topic" = "This Topic";
"lng_search_tab_this_chat" = "This Chat";
"lng_search_tab_this_channel" = "This Channel";
"lng_search_tab_this_group" = "This Group";
"lng_search_tab_public_posts" = "Public Posts";
"lng_search_tab_no_results" = "No Results";
"lng_search_tab_no_results_text" = "There were no results for \"{query}\".";
"lng_search_tab_no_results_retry" = "Try another hashtag.";
"lng_search_tab_by_hashtag" = "Enter a hashtag to find messages containing it.";
"lng_contact_details_button" = "View Contact";
"lng_contact_details_title" = "Contact details";
"lng_contact_details_phone" = "Phone";
"lng_contact_details_phone_main" = "Main Phone";
"lng_contact_details_phone_home" = "Home Phone";
"lng_contact_details_phone_mobile" = "Mobile Phone";
"lng_contact_details_phone_work" = "Work Phone";
"lng_contact_details_phone_other" = "Other Phone";
"lng_contact_details_email" = "Email";
"lng_contact_details_address" = "Address";
"lng_contact_details_url" = "URL";
"lng_contact_details_note" = "Note";
"lng_contact_details_birthday" = "Birthday";
"lng_contact_details_organization" = "Organization";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";
@@ -22,5 +22,9 @@
<file alias="hours.tgs">../../animations/hours.tgs</file>
<file alias="phone.tgs">../../animations/phone.tgs</file>
<file alias="chat_link.tgs">../../animations/chat_link.tgs</file>
<file alias="collectible_username.tgs">../../animations/collectible_username.tgs</file>
<file alias="collectible_phone.tgs">../../animations/collectible_phone.tgs</file>
<file alias="search.tgs">../../animations/search.tgs</file>
<file alias="noresults.tgs">../../animations/noresults.tgs</file>
</qresource>
</RCC>
+1 -1
View File
@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.16.0.0" />
Version="5.1.2.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,16,0,0
PRODUCTVERSION 4,16,0,0
FILEVERSION 5,1,2,0
PRODUCTVERSION 5,1,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.16.0.0"
VALUE "FileVersion", "5.1.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.16.0.0"
VALUE "ProductVersion", "5.1.2.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,16,0,0
PRODUCTVERSION 4,16,0,0
FILEVERSION 5,1,2,0
PRODUCTVERSION 5,1,2,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.16.0.0"
VALUE "FileVersion", "5.1.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.16.0.0"
VALUE "ProductVersion", "5.1.2.0"
END
END
BLOCK "VarFileInfo"
+9 -8
View File
@@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h"
#include "inline_bots/bot_attach_web_view.h"
#include "payments/payments_checkout_process.h"
#include "payments/payments_non_panel_process.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "mainwindow.h"
@@ -236,14 +237,14 @@ void SendBotCallbackDataWithPassword(
} else {
return;
}
const auto box = std::make_shared<QPointer<PasscodeBox>>();
auto fields = PasscodeBox::CloudFields::From(state);
fields.customTitle = tr::lng_bots_password_confirm_title();
fields.customDescription
= tr::lng_bots_password_confirm_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit();
fields.customCheckCallback = [=](
const Core::CloudPasswordResult &result) {
const Core::CloudPasswordResult &result,
QPointer<PasscodeBox> box) {
if (const auto button = getButton()) {
if (button->requestId) {
return;
@@ -257,18 +258,17 @@ void SendBotCallbackDataWithPassword(
return;
}
SendBotCallbackData(strongController, item, row, column, result, [=] {
if (*box) {
(*box)->closeBox();
if (box) {
box->closeBox();
}
}, [=](const QString &error) {
if (*box) {
(*box)->handleCustomCheckError(error);
if (box) {
box->handleCustomCheckError(error);
}
});
}
};
auto object = Box<PasscodeBox>(session, fields);
*box = Ui::MakeWeak(object.data());
show->showBox(std::move(object), Ui::LayerOption::CloseOther);
}, *lifetime);
}
@@ -336,7 +336,8 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
Payments::Mode::Payment,
crl::guard(controller, [=](auto) {
controller->widget()->activate();
}));
}),
Payments::ProcessNonPanelPaymentFormFactory(controller, item));
} break;
case ButtonType::Url: {
@@ -112,8 +112,8 @@ void ApplyLastList(
channel->mgInfo->lastAdmins.clear();
channel->mgInfo->lastRestricted.clear();
channel->mgInfo->lastParticipants.clear();
channel->mgInfo->lastParticipantsStatus =
MegagroupInfo::LastParticipantsUpToDate
channel->mgInfo->lastParticipantsStatus
= MegagroupInfo::LastParticipantsUpToDate
| MegagroupInfo::LastParticipantsOnceReceived;
auto botStatus = channel->mgInfo->botStatus;
@@ -212,7 +212,7 @@ void ApplyBotsList(
}
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
not_null<ChannelData*> channel,
not_null<Main::Session*> session,
const MTPmessages_Chats &chats) {
auto result = ChatParticipants::Channels();
std::vector<not_null<ChannelData*>>();
@@ -220,13 +220,13 @@ void ApplyBotsList(
const auto &list = data.vchats().v;
result.list.reserve(list.size());
for (const auto &chat : list) {
const auto peer = channel->owner().processChat(chat);
const auto peer = session->data().processChat(chat);
if (const auto channel = peer->asChannel()) {
result.list.push_back(channel);
}
}
if constexpr (MTPDmessages_chatsSlice::Is<decltype(data)>()) {
if (channel->session().premiumPossible()) {
if (session->premiumPossible()) {
result.more = data.vcount().v - data.vchats().v.size();
}
}
@@ -234,6 +234,12 @@ void ApplyBotsList(
return result;
}
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
not_null<ChannelData*> channel,
const MTPmessages_Chats &chats) {
return ParseSimilar(&channel->session(), chats);
}
} // namespace
ChatParticipant::ChatParticipant(
@@ -351,7 +357,8 @@ QString ChatParticipant::rank() const {
}
ChatParticipants::ChatParticipants(not_null<ApiWrap*> api)
: _api(&api->instance()) {
: _session(&api->session())
, _api(&api->instance()) {
}
void ChatParticipants::requestForAdd(
@@ -585,6 +592,33 @@ ChatParticipants::Parsed ChatParticipants::ParseRecent(
return result;
}
void ChatParticipants::Restrict(
not_null<ChannelData*> channel,
not_null<PeerData*> participant,
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights,
Fn<void()> onDone,
Fn<void()> onFail) {
channel->session().api().request(MTPchannels_EditBanned(
channel->inputChannel,
participant->input,
MTP_chatBannedRights(
MTP_flags(MTPDchatBannedRights::Flags::from_raw(
uint32(newRights.flags))),
MTP_int(newRights.until))
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result);
channel->applyEditBanned(participant, oldRights, newRights);
if (onDone) {
onDone();
}
}).fail([=] {
if (onFail) {
onFail();
}
}).send();
}
void ChatParticipants::requestSelf(not_null<ChannelData*> channel) {
if (_selfParticipantRequests.contains(channel)) {
return;
@@ -730,8 +764,11 @@ void ChatParticipants::loadSimilarChannels(not_null<ChannelData*> channel) {
return;
}
}
using Flag = MTPchannels_GetChannelRecommendations::Flag;
_similar[channel].requestId = _api.request(
MTPchannels_GetChannelRecommendations(channel->inputChannel)
MTPchannels_GetChannelRecommendations(
MTP_flags(Flag::f_channel),
channel->inputChannel)
).done([=](const MTPmessages_Chats &result) {
auto &similar = _similar[channel];
similar.requestId = 0;
@@ -766,4 +803,29 @@ auto ChatParticipants::similarLoaded() const
return _similarLoaded.events();
}
void ChatParticipants::loadRecommendations() {
if (_recommendationsLoaded.current() || _recommendations.requestId) {
return;
}
_recommendations.requestId = _api.request(
MTPchannels_GetChannelRecommendations(
MTP_flags(0),
MTP_inputChannelEmpty())
).done([=](const MTPmessages_Chats &result) {
_recommendations.requestId = 0;
auto parsed = ParseSimilar(_session, result);
_recommendations.channels = std::move(parsed);
_recommendations.channels.more = 0;
_recommendationsLoaded = true;
}).send();
}
const ChatParticipants::Channels &ChatParticipants::recommendations() const {
return _recommendations.channels;
}
rpl::producer<> ChatParticipants::recommendationsLoaded() const {
return _recommendationsLoaded.changes() | rpl::to_empty;
}
} // namespace Api
@@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class ApiWrap;
class ChannelData;
namespace Main {
class Session;
} // namespace Main
namespace Ui {
class Show;
} // namespace Ui
@@ -96,6 +100,13 @@ public:
static Parsed ParseRecent(
not_null<ChannelData*> channel,
const TLMembers &data);
static void Restrict(
not_null<ChannelData*> channel,
not_null<PeerData*> participant,
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights,
Fn<void()> onDone,
Fn<void()> onFail);
void add(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
@@ -134,12 +145,18 @@ public:
[[nodiscard]] auto similarLoaded() const
-> rpl::producer<not_null<ChannelData*>>;
void loadRecommendations();
[[nodiscard]] const Channels &recommendations() const;
[[nodiscard]] rpl::producer<> recommendationsLoaded() const;
private:
struct SimilarChannels {
Channels channels;
mtpRequestId requestId = 0;
};
const not_null<Main::Session*> _session;
MTP::Sender _api;
using PeerRequests = base::flat_map<PeerData*, mtpRequestId>;
@@ -165,6 +182,9 @@ private:
base::flat_map<not_null<ChannelData*>, SimilarChannels> _similar;
rpl::event_stream<not_null<ChannelData*>> _similarLoaded;
SimilarChannels _recommendations;
rpl::variable<bool> _recommendationsLoaded = false;
};
} // namespace Api
+2
View File
@@ -23,8 +23,10 @@ struct SendOptions {
PeerData *sendAs = nullptr;
TimeId scheduled = 0;
BusinessShortcutId shortcutId = 0;
EffectId effectId = 0;
bool silent = false;
bool handleSupportSwitch = false;
bool invertCaption = false;
bool hideViaBot = false;
crl::time ttlSeconds = 0;
};
@@ -62,6 +62,10 @@ void ConfirmPhone::resolve(
return bad("FirebaseSms");
}, [&](const MTPDauth_sentCodeTypeEmailCode &) {
return bad("EmailCode");
}, [&](const MTPDauth_sentCodeTypeSmsWord &) {
return bad("SmsWord");
}, [&](const MTPDauth_sentCodeTypeSmsPhrase &) {
return bad("SmsPhrase");
}, [&](const MTPDauth_sentCodeTypeSetUpEmailRequired &) {
return bad("SetUpEmailRequired");
});
@@ -93,8 +97,10 @@ void ConfirmPhone::resolve(
box->resendRequests(
) | rpl::start_with_next([=] {
_api.request(MTPauth_ResendCode(
MTP_flags(0),
MTP_string(phone),
MTP_string(phoneHash)
MTP_string(phoneHash),
MTPstring() // reason
)).done([=] {
if (boxWeak) {
boxWeak->callDone();
+222
View File
@@ -0,0 +1,222 @@
/*
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_credits.h"
#include "apiwrap.h"
#include "api/api_updates.h"
#include "base/unixtime.h"
#include "data/data_peer.h"
#include "data/data_photo.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
namespace Api {
namespace {
[[nodiscard]] Data::CreditsHistoryEntry HistoryFromTL(
const MTPStarsTransaction &tl,
not_null<PeerData*> peer) {
using HistoryPeerTL = MTPDstarsTransactionPeer;
const auto photo = tl.data().vphoto()
? peer->owner().photoFromWeb(*tl.data().vphoto(), ImageLocation())
: nullptr;
return Data::CreditsHistoryEntry{
.id = qs(tl.data().vid()),
.title = qs(tl.data().vtitle().value_or_empty()),
.description = qs(tl.data().vdescription().value_or_empty()),
.date = base::unixtime::parse(tl.data().vdate().v),
.photoId = photo ? photo->id : 0,
.credits = tl.data().vstars().v,
.bareId = tl.data().vpeer().match([](const HistoryPeerTL &p) {
return peerFromMTP(p.vpeer());
}, [](const auto &) {
return PeerId(0);
}).value,
.peerType = tl.data().vpeer().match([](const HistoryPeerTL &) {
return Data::CreditsHistoryEntry::PeerType::Peer;
}, [](const MTPDstarsTransactionPeerPlayMarket &) {
return Data::CreditsHistoryEntry::PeerType::PlayMarket;
}, [](const MTPDstarsTransactionPeerFragment &) {
return Data::CreditsHistoryEntry::PeerType::Fragment;
}, [](const MTPDstarsTransactionPeerAppStore &) {
return Data::CreditsHistoryEntry::PeerType::AppStore;
}, [](const MTPDstarsTransactionPeerUnsupported &) {
return Data::CreditsHistoryEntry::PeerType::Unsupported;
}, [](const MTPDstarsTransactionPeerPremiumBot &) {
return Data::CreditsHistoryEntry::PeerType::PremiumBot;
}),
.refunded = tl.data().is_refund(),
};
}
[[nodiscard]] Data::CreditsStatusSlice StatusFromTL(
const MTPpayments_StarsStatus &status,
not_null<PeerData*> peer) {
peer->owner().processUsers(status.data().vusers());
peer->owner().processChats(status.data().vchats());
return Data::CreditsStatusSlice{
.list = ranges::views::all(
status.data().vhistory().v
) | ranges::views::transform([&](const MTPStarsTransaction &tl) {
return HistoryFromTL(tl, peer);
}) | ranges::to_vector,
.balance = status.data().vbalance().v,
.allLoaded = !status.data().vnext_offset().has_value(),
.token = qs(status.data().vnext_offset().value_or_empty()),
};
}
} // namespace
CreditsTopupOptions::CreditsTopupOptions(not_null<PeerData*> peer)
: _peer(peer)
, _api(&peer->session().api().instance()) {
}
rpl::producer<rpl::no_value, QString> CreditsTopupOptions::request() {
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
using TLOption = MTPStarsTopupOption;
_api.request(MTPpayments_GetStarsTopupOptions(
)).done([=](const MTPVector<TLOption> &result) {
_options = ranges::views::all(
result.v
) | ranges::views::transform([](const TLOption &option) {
return Data::CreditTopupOption{
.credits = option.data().vstars().v,
.product = qs(
option.data().vstore_product().value_or_empty()),
.currency = qs(option.data().vcurrency()),
.amount = option.data().vamount().v,
.extended = option.data().is_extended(),
};
}) | ranges::to_vector;
consumer.put_done();
}).fail([=](const MTP::Error &error) {
consumer.put_error_copy(error.type());
}).send();
return lifetime;
};
}
CreditsStatus::CreditsStatus(not_null<PeerData*> peer)
: _peer(peer)
, _api(&peer->session().api().instance()) {
}
void CreditsStatus::request(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done) {
if (_requestId) {
return;
}
using TLResult = MTPpayments_StarsStatus;
_requestId = _api.request(MTPpayments_GetStarsStatus(
_peer->isSelf() ? MTP_inputPeerSelf() : _peer->input
)).done([=](const TLResult &result) {
_requestId = 0;
done(StatusFromTL(result, _peer));
}).fail([=] {
_requestId = 0;
done({});
}).send();
}
CreditsHistory::CreditsHistory(not_null<PeerData*> peer, bool in, bool out)
: _peer(peer)
, _flags((in == out)
? HistoryTL::Flags(0)
: HistoryTL::Flags(0)
| (in ? HistoryTL::Flag::f_inbound : HistoryTL::Flags(0))
| (out ? HistoryTL::Flag::f_outbound : HistoryTL::Flags(0)))
, _api(&peer->session().api().instance()) {
}
void CreditsHistory::request(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done) {
if (_requestId) {
return;
}
_requestId = _api.request(MTPpayments_GetStarsTransactions(
MTP_flags(_flags),
_peer->isSelf() ? MTP_inputPeerSelf() : _peer->input,
MTP_string(token)
)).done([=](const MTPpayments_StarsStatus &result) {
_requestId = 0;
done(StatusFromTL(result, _peer));
}).fail([=] {
_requestId = 0;
done({});
}).send();
}
Data::CreditTopupOptions CreditsTopupOptions::options() const {
return _options;
}
rpl::producer<not_null<PeerData*>> PremiumPeerBot(
not_null<Main::Session*> session) {
const auto username = session->appConfig().get<QString>(
u"premium_bot_username"_q,
QString());
if (username.isEmpty()) {
return rpl::never<not_null<PeerData*>>();
}
if (const auto p = session->data().peerByUsername(username)) {
return rpl::single<not_null<PeerData*>>(p);
}
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
const auto api = lifetime.make_state<MTP::Sender>(&session->mtp());
api->request(MTPcontacts_ResolveUsername(
MTP_string(username)
)).done([=](const MTPcontacts_ResolvedPeer &result) {
session->data().processUsers(result.data().vusers());
session->data().processChats(result.data().vchats());
const auto botPeer = session->data().peerLoaded(
peerFromMTP(result.data().vpeer()));
if (!botPeer) {
return consumer.put_done();
}
consumer.put_next(not_null{ botPeer });
}).send();
return lifetime;
};
}
void CreditsRefund(
not_null<PeerData*> peer,
const QString &entryId,
Fn<void()> done,
Fn<void(QString)> fail) {
const auto user = peer->asUser();
if (!user) {
return;
}
peer->session().api().request(MTPpayments_RefundStarsCharge(
user->inputUser,
MTP_string(entryId)
)).done([=](const MTPUpdates &result) {
peer->session().api().updates().applyUpdates(result);
done();
}).fail([=](const MTP::Error &error) {
fail(error.type());
}).send();
}
} // namespace Api
+80
View File
@@ -0,0 +1,80 @@
/*
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 "data/data_credits.h"
#include "mtproto/sender.h"
namespace Main {
class Session;
} // namespace Main
namespace Api {
class CreditsTopupOptions final {
public:
CreditsTopupOptions(not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
[[nodiscard]] Data::CreditTopupOptions options() const;
private:
const not_null<PeerData*> _peer;
Data::CreditTopupOptions _options;
MTP::Sender _api;
};
class CreditsStatus final {
public:
CreditsStatus(not_null<PeerData*> peer);
void request(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done);
private:
const not_null<PeerData*> _peer;
mtpRequestId _requestId = 0;
MTP::Sender _api;
};
class CreditsHistory final {
public:
CreditsHistory(not_null<PeerData*> peer, bool in, bool out);
void request(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done);
private:
using HistoryTL = MTPpayments_GetStarsTransactions;
const not_null<PeerData*> _peer;
const HistoryTL::Flags _flags;
mtpRequestId _requestId = 0;
MTP::Sender _api;
};
void CreditsRefund(
not_null<PeerData*> peer,
const QString &entryId,
Fn<void()> done,
Fn<void(QString)> fail);
[[nodiscard]] rpl::producer<not_null<PeerData*>> PremiumPeerBot(
not_null<Main::Session*> session);
} // namespace Api
+19 -11
View File
@@ -58,25 +58,33 @@ void HandleWithdrawalButton(
state->loading = false;
auto fields = PasscodeBox::CloudFields::From(pass);
fields.customTitle =
tr::lng_channel_earn_balance_password_title();
fields.customDescription =
tr::lng_channel_earn_balance_password_description(tr::now);
fields.customTitle
= tr::lng_channel_earn_balance_password_title();
fields.customDescription
= tr::lng_channel_earn_balance_password_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit();
fields.customCheckCallback = crl::guard(button, [=](
const Core::CloudPasswordResult &result) {
const Core::CloudPasswordResult &result,
QPointer<PasscodeBox> box) {
const auto done = [=](const QString &result) {
if (!result.isEmpty()) {
UrlClickHandler::Open(result);
if (box) {
box->closeBox();
}
}
};
const auto fail = [=](const QString &error) {
show->showToast(error);
};
session->api().request(
MTPstats_GetBroadcastRevenueWithdrawalUrl(
channel->inputChannel,
result.result
)).done([=](const MTPstats_BroadcastRevenueWithdrawalUrl &r) {
const auto url = qs(r.data().vurl());
if (!url.isEmpty()) {
UrlClickHandler::Open(url);
}
done(qs(r.data().vurl()));
}).fail([=](const MTP::Error &error) {
show->showToast(error.type());
fail(error.type());
}).send();
});
show->show(Box<PasscodeBox>(session, fields));
+107 -16
View File
@@ -12,12 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h"
#include "ui/boxes/confirm_box.h"
#include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h"
#include "data/data_web_page.h"
#include "history/view/controls/history_view_compose_media_edit_manager.h"
#include "history/history.h"
#include "history/history_item.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mtproto/mtproto_response.h"
@@ -29,20 +30,20 @@ namespace {
using namespace rpl::details;
template <typename T>
constexpr auto WithId =
is_callable_plain_v<T, Fn<void()>, mtpRequestId>;
constexpr auto WithId
= is_callable_plain_v<T, Fn<void()>, mtpRequestId>;
template <typename T>
constexpr auto WithoutId =
is_callable_plain_v<T, Fn<void()>>;
constexpr auto WithoutId
= is_callable_plain_v<T, Fn<void()>>;
template <typename T>
constexpr auto WithoutCallback =
is_callable_plain_v<T>;
constexpr auto WithoutCallback
= is_callable_plain_v<T>;
template <typename T>
constexpr auto ErrorWithId =
is_callable_plain_v<T, QString, mtpRequestId>;
constexpr auto ErrorWithId
= is_callable_plain_v<T, QString, mtpRequestId>;
template <typename T>
constexpr auto ErrorWithoutId =
is_callable_plain_v<T, QString>;
constexpr auto ErrorWithoutId
= is_callable_plain_v<T, QString>;
template <typename DoneCallback, typename FailCallback>
mtpRequestId EditMessage(
@@ -81,7 +82,8 @@ mtpRequestId EditMessage(
| ((!webpage.removed && !webpage.url.isEmpty())
? MTPmessages_EditMessage::Flag::f_media
: emptyFlag)
| ((!webpage.removed && !webpage.url.isEmpty() && webpage.invert)
| (((!webpage.removed && !webpage.url.isEmpty() && webpage.invert)
|| options.invertCaption)
? MTPmessages_EditMessage::Flag::f_invert_media
: emptyFlag)
| (!sentEntities.v.isEmpty()
@@ -95,7 +97,7 @@ mtpRequestId EditMessage(
: emptyFlag);
const auto id = item->isScheduled()
? session->data().scheduledMessages().lookupId(item)
? session->scheduledMessages().lookupId(item)
: item->isBusinessShortcut()
? session->data().shortcutMessages().lookupId(item)
: item->id;
@@ -203,6 +205,7 @@ void RescheduleMessage(
not_null<HistoryItem*> item,
SendOptions options) {
const auto empty = [] {};
options.invertCaption = item->invertMedia();
EditMessage(item, options, empty, empty);
}
@@ -253,12 +256,100 @@ mtpRequestId EditTextMessage(
Data::WebPageDraft webpage,
SendOptions options,
Fn<void(mtpRequestId requestId)> done,
Fn<void(const QString &, mtpRequestId requestId)> fail) {
Fn<void(const QString &error, mtpRequestId requestId)> fail,
bool spoilered) {
const auto media = item->media();
if (media
&& HistoryView::MediaEditManager::CanBeSpoilered(item)
&& spoilered != media->hasSpoiler()) {
auto takeInputMedia = Fn<std::optional<MTPInputMedia>()>(nullptr);
auto takeFileReference = Fn<QByteArray()>(nullptr);
if (const auto photo = media->photo()) {
using Flag = MTPDinputMediaPhoto::Flag;
const auto flags = Flag()
| (media->ttlSeconds() ? Flag::f_ttl_seconds : Flag())
| (spoilered ? Flag::f_spoiler : Flag());
takeInputMedia = [=] {
return MTP_inputMediaPhoto(
MTP_flags(flags),
photo->mtpInput(),
MTP_int(media->ttlSeconds()));
};
takeFileReference = [=] { return photo->fileReference(); };
} else if (const auto document = media->document()) {
using Flag = MTPDinputMediaDocument::Flag;
const auto flags = Flag()
| (media->ttlSeconds() ? Flag::f_ttl_seconds : Flag())
| (spoilered ? Flag::f_spoiler : Flag());
takeInputMedia = [=] {
return MTP_inputMediaDocument(
MTP_flags(flags),
document->mtpInput(),
MTP_int(media->ttlSeconds()),
MTPstring()); // query
};
takeFileReference = [=] { return document->fileReference(); };
}
const auto usedFileReference = takeFileReference
? takeFileReference()
: QByteArray();
const auto origin = item->fullId();
const auto api = &item->history()->session().api();
const auto performRequest = [=](
const auto &repeatRequest,
mtpRequestId originalRequestId) -> mtpRequestId {
const auto handleReference = [=](
const QString &error,
mtpRequestId requestId) {
if (error.startsWith(u"FILE_REFERENCE_"_q)) {
api->refreshFileReference(origin, [=](const auto &) {
if (takeFileReference &&
(takeFileReference() != usedFileReference)) {
repeatRequest(
repeatRequest,
originalRequestId
? originalRequestId
: requestId);
} else {
fail(error, requestId);
}
});
} else {
fail(error, requestId);
}
};
const auto callback = [=](
Fn<void()> applyUpdates,
mtpRequestId requestId) {
applyUpdates();
done(originalRequestId ? originalRequestId : requestId);
};
const auto requestId = EditMessage(
item,
caption,
webpage,
options,
callback,
handleReference,
takeInputMedia ? takeInputMedia() : std::nullopt);
return originalRequestId ? originalRequestId : requestId;
};
return performRequest(performRequest, 0);
}
const auto callback = [=](Fn<void()> applyUpdates, mtpRequestId id) {
applyUpdates();
done(id);
};
return EditMessage(item, caption, webpage, options, callback, fail);
return EditMessage(
item,
caption,
webpage,
options,
callback,
fail,
std::nullopt);
}
} // namespace Api
+2 -1
View File
@@ -55,6 +55,7 @@ mtpRequestId EditTextMessage(
Data::WebPageDraft webpage,
SendOptions options,
Fn<void(mtpRequestId requestId)> done,
Fn<void(const QString &error, mtpRequestId requestId)> fail);
Fn<void(const QString &error, mtpRequestId requestId)> fail,
bool spoilered);
} // namespace Api
+13 -20
View File
@@ -34,7 +34,7 @@ namespace {
constexpr auto kSharedMediaLimit = 100;
[[nodiscard]] SendMediaReady PreparePeerPhoto(
[[nodiscard]] std::shared_ptr<FilePrepareResult> PreparePeerPhoto(
MTP::DcId dcId,
PeerId peerId,
QImage &&image) {
@@ -80,24 +80,17 @@ constexpr auto kSharedMediaLimit = 100;
MTPVector<MTPVideoSize>(),
MTP_int(dcId));
QString file, filename;
int64 filesize = 0;
QByteArray data;
return SendMediaReady(
SendMediaType::Photo,
file,
filename,
filesize,
data,
id,
id,
u"jpg"_q,
peerId,
photo,
photoThumbs,
MTP_documentEmpty(MTP_long(0)),
jpeg);
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::Photo,
});
result->type = SendMediaType::Photo;
result->setFileData(jpeg);
result->thumbId = id;
result->thumbname = "thumb.jpg";
result->photo = photo;
result->photoThumbs = photoThumbs;
return result;
}
[[nodiscard]] std::optional<MTPVideoSize> PrepareMtpMarkup(
@@ -239,7 +232,7 @@ void PeerPhoto::upload(
_api.instance().mainDcId(),
peer->id,
base::take(photo.image));
_session->uploader().uploadMedia(fakeId, ready);
_session->uploader().upload(fakeId, ready);
}
}
+5 -1
View File
@@ -73,6 +73,9 @@ void Polls::create(
if (action.options.shortcutId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
if (action.options.effectId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
}
const auto sendAs = action.options.sendAs;
if (sendAs) {
sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
@@ -94,7 +97,8 @@ void Polls::create(
MTPVector<MTPMessageEntity>(),
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, action.options.shortcutId)
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
MTP_long(action.options.effectId)
), [=](const MTPUpdates &result, const MTP::Response &response) {
if (clearCloudDraft) {
history->finishSavingCloudDraft(
+35
View File
@@ -602,6 +602,41 @@ bool PremiumGiftCodeOptions::giveawayGiftsPurchaseAvailable() const {
false);
}
SponsoredToggle::SponsoredToggle(not_null<Main::Session*> session)
: _api(&session->api().instance()) {
}
rpl::producer<bool> SponsoredToggle::toggled() {
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
_api.request(MTPusers_GetFullUser(
MTP_inputUserSelf()
)).done([=](const MTPusers_UserFull &result) {
consumer.put_next_copy(
result.data().vfull_user().data().is_sponsored_enabled());
}).fail([=] { consumer.put_next(false); }).send();
return lifetime;
};
}
rpl::producer<rpl::no_value, QString> SponsoredToggle::setToggled(bool v) {
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
_api.request(MTPaccount_ToggleSponsoredMessages(
MTP_bool(v)
)).done([=] {
consumer.put_done();
}).fail([=](const MTP::Error &error) {
consumer.put_error_copy(error.type());
}).send();
return lifetime;
};
}
RequirePremiumState ResolveRequiresPremiumToWrite(
not_null<PeerData*> peer,
History *maybeHistory) {
+12
View File
@@ -216,6 +216,18 @@ private:
};
class SponsoredToggle final {
public:
explicit SponsoredToggle(not_null<Main::Session*> session);
[[nodiscard]] rpl::producer<bool> toggled();
[[nodiscard]] rpl::producer<rpl::no_value, QString> setToggled(bool);
private:
MTP::Sender _api;
};
enum class RequirePremiumState {
Unknown,
Yes,
+14 -19
View File
@@ -24,16 +24,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api {
namespace {
SendMediaReady PrepareRingtoneDocument(
std::shared_ptr<FilePrepareResult> PrepareRingtoneDocument(
MTP::DcId dcId,
const QString &filename,
const QString &filemime,
const QByteArray &content) {
const auto id = base::RandomValue<DocumentId>();
auto attributes = QVector<MTPDocumentAttribute>(
1,
MTP_documentAttributeFilename(MTP_string(filename)));
const auto id = base::RandomValue<DocumentId>();
const auto document = MTP_document(
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::File,
});
result->filename = filename;
result->content = content;
result->filesize = content.size();
result->setFileData(content);
result->document = MTP_document(
MTP_flags(0),
MTP_long(id),
MTP_long(0),
@@ -45,21 +54,7 @@ SendMediaReady PrepareRingtoneDocument(
MTPVector<MTPVideoSize>(),
MTP_int(dcId),
MTP_vector<MTPDocumentAttribute>(std::move(attributes)));
return SendMediaReady(
SendMediaType::File,
QString(), // filepath
filename,
content.size(),
content,
id,
0,
QString(),
PeerId(),
MTP_photoEmpty(MTP_long(0)),
PreparedPhotoThumbs(),
document,
QByteArray());
return result;
}
} // namespace
@@ -102,7 +97,7 @@ void Ringtones::upload(
_uploads.erase(already);
}
_uploads.emplace(fakeId, uploadedData);
_session->uploader().uploadMedia(fakeId, ready);
_session->uploader().upload(fakeId, ready);
}
void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) {
+26 -3
View File
@@ -133,6 +133,13 @@ void SendExistingMedia(
flags |= MessageFlag::ShortcutMessage;
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
if (action.options.effectId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
}
if (action.options.invertCaption) {
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
}
session->data().registerMessageRandomId(randomId, newId);
@@ -144,6 +151,7 @@ void SendExistingMedia(
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
.effectId = action.options.effectId,
}, media, caption);
const auto performRequest = [=](const auto &repeatRequest) -> void {
@@ -165,7 +173,8 @@ void SendExistingMedia(
sentEntities,
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId)
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId)
), [=](const MTPUpdates &result, const MTP::Response &response) {
}, [=](const MTP::Error &error, const MTP::Response &response) {
if (error.code() == 400
@@ -306,6 +315,13 @@ bool SendDice(MessageToSend &message) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
if (action.options.effectId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
}
if (action.options.invertCaption) {
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
}
session->data().registerMessageRandomId(randomId, newId);
@@ -317,6 +333,7 @@ bool SendDice(MessageToSend &message) {
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
.effectId = action.options.effectId,
}, TextWithEntities(), MTP_messageMediaDice(
MTP_int(0),
MTP_string(emoji)));
@@ -335,7 +352,8 @@ bool SendDice(MessageToSend &message) {
MTP_vector<MTPMessageEntity>(),
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId)
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId)
), [=](const MTPUpdates &result, const MTP::Response &response) {
}, [=](const MTP::Error &error, const MTP::Response &response) {
api->sendMessageFail(error, peer, randomId, newId);
@@ -353,7 +371,7 @@ void FillMessagePostFlags(
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file) {
const std::shared_ptr<FilePrepareResult> &file) {
const auto isEditing = (file->type != SendMediaType::Audio)
&& (file->to.replaceMediaOf != 0);
const auto newId = FullMsgId(
@@ -430,6 +448,9 @@ void SendConfirmedFile(
flags |= MessageFlag::MediaIsUnread;
}
}
if (file->to.options.invertCaption) {
flags |= MessageFlag::InvertMedia;
}
const auto messageFromId = file->to.options.sendAs
? file->to.options.sendAs->id
@@ -493,6 +514,7 @@ void SendConfirmedFile(
edition.ttl = 0;
edition.mtpMedia = &media;
edition.textWithEntities = caption;
edition.invertMedia = file->to.options.invertCaption;
edition.useSameViews = true;
edition.useSameForwards = true;
edition.useSameMarkup = true;
@@ -510,6 +532,7 @@ void SendConfirmedFile(
.shortcutId = file->to.options.shortcutId,
.postAuthor = messagePostAuthor,
.groupedId = groupId,
.effectId = file->to.options.effectId,
}, caption, media);
}
+2 -2
View File
@@ -14,7 +14,7 @@ class Session;
class History;
class PhotoData;
class DocumentData;
struct FileLoadResult;
struct FilePrepareResult;
namespace Api {
@@ -40,6 +40,6 @@ void FillMessagePostFlags(
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file);
const std::shared_ptr<FilePrepareResult> &file);
} // namespace Api
+5 -4
View File
@@ -760,14 +760,14 @@ rpl::producer<rpl::no_value, QString> EarnStatistics::request() {
channel()->inputChannel
)).done([=](const MTPstats_BroadcastRevenueStats &result) {
const auto &data = result.data();
const auto &balances = data.vbalances().data();
_data = Data::EarnStatistics{
.topHoursGraph = StatisticalGraphFromTL(
data.vtop_hours_graph()),
.revenueGraph = StatisticalGraphFromTL(data.vrevenue_graph()),
.currentBalance = data.vcurrent_balance().v,
.availableBalance = data.vavailable_balance().v,
.overallRevenue = data.voverall_revenue().v,
.currentBalance = balances.vcurrent_balance().v,
.availableBalance = balances.vavailable_balance().v,
.overallRevenue = balances.voverall_revenue().v,
.usdRate = data.vusd_rate().v,
};
@@ -860,6 +860,7 @@ void EarnStatistics::requestHistory(
.token = Data::EarnHistorySlice::OffsetToken(nextToken),
});
}).fail([=] {
done({});
_requestId = 0;
}).send();
}
+241 -81
View File
@@ -7,12 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "api/api_text_entities.h"
#include "main/main_session.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers_set.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_user.h"
#include "main/main_session.h"
namespace Api {
namespace {
@@ -62,67 +62,168 @@ using namespace TextUtilities;
EntitiesInText EntitiesFromMTP(
Main::Session *session,
const QVector<MTPMessageEntity> &entities) {
if (entities.isEmpty()) {
return {};
}
auto result = EntitiesInText();
if (!entities.isEmpty()) {
result.reserve(entities.size());
for (const auto &entity : entities) {
switch (entity.type()) {
case mtpc_messageEntityUrl: { auto &d = entity.c_messageEntityUrl(); result.push_back({ EntityType::Url, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityTextUrl: { auto &d = entity.c_messageEntityTextUrl(); result.push_back({ EntityType::CustomUrl, d.voffset().v, d.vlength().v, qs(d.vurl()) }); } break;
case mtpc_messageEntityEmail: { auto &d = entity.c_messageEntityEmail(); result.push_back({ EntityType::Email, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityHashtag: { auto &d = entity.c_messageEntityHashtag(); result.push_back({ EntityType::Hashtag, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityCashtag: { auto &d = entity.c_messageEntityCashtag(); result.push_back({ EntityType::Cashtag, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityPhone: break; // Skipping phones.
case mtpc_messageEntityMention: { auto &d = entity.c_messageEntityMention(); result.push_back({ EntityType::Mention, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityMentionName: if (session) {
const auto &d = entity.c_messageEntityMentionName();
const auto userId = UserId(d.vuser_id());
const auto user = session->data().userLoaded(userId);
const auto data = MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = userId.bare,
.accessHash = user ? user->accessHash() : 0,
});
result.push_back({ EntityType::MentionName, d.voffset().v, d.vlength().v, data });
} break;
case mtpc_inputMessageEntityMentionName: if (session) {
const auto &d = entity.c_inputMessageEntityMentionName();
const auto data = d.vuser_id().match([&](
const MTPDinputUserSelf &) {
return MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = session->userId().bare,
.accessHash = session->user()->accessHash(),
});
}, [&](const MTPDinputUser &data) {
return MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = UserId(data.vuser_id()).bare,
.accessHash = data.vaccess_hash().v,
});
}, [&](const auto &) {
return QString();
});
if (!data.isEmpty()) {
result.push_back({ EntityType::MentionName, d.voffset().v, d.vlength().v, data });
}
} break;
case mtpc_messageEntityBotCommand: { auto &d = entity.c_messageEntityBotCommand(); result.push_back({ EntityType::BotCommand, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityBold: { auto &d = entity.c_messageEntityBold(); result.push_back({ EntityType::Bold, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityItalic: { auto &d = entity.c_messageEntityItalic(); result.push_back({ EntityType::Italic, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityUnderline: { auto &d = entity.c_messageEntityUnderline(); result.push_back({ EntityType::Underline, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityStrike: { auto &d = entity.c_messageEntityStrike(); result.push_back({ EntityType::StrikeOut, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityCode: { auto &d = entity.c_messageEntityCode(); result.push_back({ EntityType::Code, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityPre: { auto &d = entity.c_messageEntityPre(); result.push_back({ EntityType::Pre, d.voffset().v, d.vlength().v, qs(d.vlanguage()) }); } break;
case mtpc_messageEntityBlockquote: { auto &d = entity.c_messageEntityBlockquote(); result.push_back({ EntityType::Blockquote, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityBankCard: break; // Skipping cards. // #TODO entities
case mtpc_messageEntitySpoiler: { auto &d = entity.c_messageEntitySpoiler(); result.push_back({ EntityType::Spoiler, d.voffset().v, d.vlength().v }); } break;
case mtpc_messageEntityCustomEmoji: {
const auto &d = entity.c_messageEntityCustomEmoji();
result.push_back({ EntityType::CustomEmoji, d.voffset().v, d.vlength().v, CustomEmojiEntityData(d) });
} break;
result.reserve(entities.size());
for (const auto &entity : entities) {
entity.match([&](const MTPDmessageEntityUnknown &d) {
}, [&](const MTPDmessageEntityMention &d) {
result.push_back({
EntityType::Mention,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityHashtag &d) {
result.push_back({
EntityType::Hashtag,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityBotCommand &d) {
result.push_back({
EntityType::BotCommand,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityUrl &d) {
result.push_back({
EntityType::Url,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityEmail &d) {
result.push_back({
EntityType::Email,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityBold &d) {
result.push_back({
EntityType::Bold,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityItalic &d) {
result.push_back({
EntityType::Italic,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityCode &d) {
result.push_back({
EntityType::Code,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityPre &d) {
result.push_back({
EntityType::Pre,
d.voffset().v,
d.vlength().v,
qs(d.vlanguage()),
});
}, [&](const MTPDmessageEntityTextUrl &d) {
result.push_back({
EntityType::CustomUrl,
d.voffset().v,
d.vlength().v,
qs(d.vurl()),
});
}, [&](const MTPDmessageEntityMentionName &d) {
if (!session) {
return;
}
}
const auto userId = UserId(d.vuser_id());
const auto user = session->data().userLoaded(userId);
const auto data = MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = userId.bare,
.accessHash = user ? user->accessHash() : 0,
});
result.push_back({
EntityType::MentionName,
d.voffset().v,
d.vlength().v,
data,
});
}, [&](const MTPDinputMessageEntityMentionName &d) {
if (!session) {
return;
}
const auto data = d.vuser_id().match([&](
const MTPDinputUserSelf &) {
return MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = session->userId().bare,
.accessHash = session->user()->accessHash(),
});
}, [&](const MTPDinputUser &data) {
return MentionNameDataFromFields({
.selfId = session->userId().bare,
.userId = UserId(data.vuser_id()).bare,
.accessHash = data.vaccess_hash().v,
});
}, [](const auto &) {
return QString();
});
if (!data.isEmpty()) {
result.push_back({
EntityType::MentionName,
d.voffset().v,
d.vlength().v,
data,
});
}
}, [&](const MTPDmessageEntityPhone &d) {
result.push_back({
EntityType::Phone,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityCashtag &d) {
result.push_back({
EntityType::Cashtag,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityUnderline &d) {
result.push_back({
EntityType::Underline,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityStrike &d) {
result.push_back({
EntityType::StrikeOut,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityBankCard &d) {
// Skipping cards. // #TODO entities
}, [&](const MTPDmessageEntitySpoiler &d) {
result.push_back({
EntityType::Spoiler,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntityCustomEmoji &d) {
result.push_back({
EntityType::CustomEmoji,
d.voffset().v,
d.vlength().v,
CustomEmojiEntityData(d),
});
}, [&](const MTPDmessageEntityBlockquote &d) {
result.push_back({
EntityType::Blockquote,
d.voffset().v,
d.vlength().v,
d.is_collapsed() ? u"1"_q : QString(),
});
});
}
return result;
}
@@ -134,7 +235,9 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
auto v = QVector<MTPMessageEntity>();
v.reserve(entities.size());
for (const auto &entity : entities) {
if (entity.length() <= 0) continue;
if (entity.length() <= 0) {
continue;
}
if (option == ConvertOption::SkipLocal
&& entity.type() != EntityType::Bold
//&& entity.type() != EntityType::Semibold // Not in API.
@@ -154,28 +257,85 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
auto offset = MTP_int(entity.offset());
auto length = MTP_int(entity.length());
switch (entity.type()) {
case EntityType::Url: v.push_back(MTP_messageEntityUrl(offset, length)); break;
case EntityType::CustomUrl: v.push_back(MTP_messageEntityTextUrl(offset, length, MTP_string(entity.data()))); break;
case EntityType::Email: v.push_back(MTP_messageEntityEmail(offset, length)); break;
case EntityType::Hashtag: v.push_back(MTP_messageEntityHashtag(offset, length)); break;
case EntityType::Cashtag: v.push_back(MTP_messageEntityCashtag(offset, length)); break;
case EntityType::Mention: v.push_back(MTP_messageEntityMention(offset, length)); break;
case EntityType::Url: {
v.push_back(MTP_messageEntityUrl(offset, length));
} break;
case EntityType::CustomUrl: {
v.push_back(
MTP_messageEntityTextUrl(
offset,
length,
MTP_string(entity.data())));
} break;
case EntityType::Email: {
v.push_back(MTP_messageEntityEmail(offset, length));
} break;
case EntityType::Phone: {
v.push_back(MTP_messageEntityPhone(offset, length));
} break;
case EntityType::Hashtag: {
v.push_back(MTP_messageEntityHashtag(offset, length));
} break;
case EntityType::Cashtag: {
v.push_back(MTP_messageEntityCashtag(offset, length));
} break;
case EntityType::Mention: {
v.push_back(MTP_messageEntityMention(offset, length));
} break;
case EntityType::MentionName: {
if (const auto valid = MentionNameEntity(session, offset, length, entity.data())) {
const auto valid = MentionNameEntity(
session,
offset,
length,
entity.data());
if (valid) {
v.push_back(*valid);
}
} break;
case EntityType::BotCommand: v.push_back(MTP_messageEntityBotCommand(offset, length)); break;
case EntityType::Bold: v.push_back(MTP_messageEntityBold(offset, length)); break;
case EntityType::Italic: v.push_back(MTP_messageEntityItalic(offset, length)); break;
case EntityType::Underline: v.push_back(MTP_messageEntityUnderline(offset, length)); break;
case EntityType::StrikeOut: v.push_back(MTP_messageEntityStrike(offset, length)); break;
case EntityType::Code: v.push_back(MTP_messageEntityCode(offset, length)); break; // #TODO entities
case EntityType::Pre: v.push_back(MTP_messageEntityPre(offset, length, MTP_string(entity.data()))); break;
case EntityType::Blockquote: v.push_back(MTP_messageEntityBlockquote(offset, length)); break;
case EntityType::Spoiler: v.push_back(MTP_messageEntitySpoiler(offset, length)); break;
case EntityType::BotCommand: {
v.push_back(MTP_messageEntityBotCommand(offset, length));
} break;
case EntityType::Bold: {
v.push_back(MTP_messageEntityBold(offset, length));
} break;
case EntityType::Italic: {
v.push_back(MTP_messageEntityItalic(offset, length));
} break;
case EntityType::Underline: {
v.push_back(MTP_messageEntityUnderline(offset, length));
} break;
case EntityType::StrikeOut: {
v.push_back(MTP_messageEntityStrike(offset, length));
} break;
case EntityType::Code: {
// #TODO entities.
v.push_back(MTP_messageEntityCode(offset, length));
} break;
case EntityType::Pre: {
v.push_back(
MTP_messageEntityPre(
offset,
length,
MTP_string(entity.data())));
} break;
case EntityType::Blockquote: {
using Flag = MTPDmessageEntityBlockquote::Flag;
const auto collapsed = !entity.data().isEmpty();
v.push_back(
MTP_messageEntityBlockquote(
MTP_flags(collapsed ? Flag::f_collapsed : Flag()),
offset,
length));
} break;
case EntityType::Spoiler: {
v.push_back(MTP_messageEntitySpoiler(offset, length));
} break;
case EntityType::CustomEmoji: {
if (const auto valid = CustomEmojiEntity(offset, length, entity.data())) {
const auto valid = CustomEmojiEntity(
offset,
length,
entity.data());
if (valid) {
v.push_back(*valid);
}
} break;
+25 -8
View File
@@ -21,6 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/components/top_peers.h"
#include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_saved_messages.h"
@@ -37,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h"
#include "data/data_folder.h"
#include "data/data_forum.h"
#include "data/data_scheduled_messages.h"
#include "data/data_send_action.h"
#include "data/data_stories.h"
#include "data/data_message_reactions.h"
@@ -98,7 +99,7 @@ void ProcessScheduledMessageWithElapsedTime(
// Note that when a message is scheduled until online
// while the recipient is already online, the server sends
// an ordinary new message with skipped "from_scheduled" flag.
session->data().scheduledMessages().checkEntitiesAndUpdate(data);
session->scheduledMessages().checkEntitiesAndUpdate(data);
}
}
@@ -1144,7 +1145,9 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPMessageReactions(),
MTPVector<MTPRestrictionReason>(),
MTP_int(d.vttl_period().value_or_empty()),
MTPint()), // quick_reply_shortcut_id
MTPint(), // quick_reply_shortcut_id
MTPlong(), // effect
MTPFactCheck()),
MessageFlags(),
NewMessageType::Unread);
} break;
@@ -1179,7 +1182,9 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPMessageReactions(),
MTPVector<MTPRestrictionReason>(),
MTP_int(d.vttl_period().value_or_empty()),
MTPint()), // quick_reply_shortcut_id
MTPint(), // quick_reply_shortcut_id
MTPlong(), // effect
MTPFactCheck()),
MessageFlags(),
NewMessageType::Unread);
} break;
@@ -1472,7 +1477,9 @@ void Updates::applyUpdates(
if (const auto id = owner.messageIdByRandomId(randomId)) {
const auto local = owner.message(id);
if (local && local->isScheduled()) {
owner.scheduledMessages().sendNowSimpleMessage(d, local);
session().scheduledMessages().sendNowSimpleMessage(
d,
local);
}
}
const auto wasAlready = (lookupMessage() != nullptr);
@@ -1569,7 +1576,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
auto &owner = session().data();
if (const auto local = owner.message(id)) {
if (local->isScheduled()) {
session().data().scheduledMessages().apply(d, local);
session().scheduledMessages().apply(d, local);
} else if (local->isBusinessShortcut()) {
session().data().shortcutMessages().apply(d, local);
} else {
@@ -1583,6 +1590,11 @@ void Updates::feedUpdate(const MTPUpdate &update) {
} else {
if (existing) {
existing->destroy();
} else {
// Not the server-side date, but close enough.
session().topPeers().increment(
local->history()->peer,
local->date());
}
local->setRealId(d.vid().v);
}
@@ -1779,12 +1791,12 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateNewScheduledMessage: {
const auto &d = update.c_updateNewScheduledMessage();
session().data().scheduledMessages().apply(d);
session().scheduledMessages().apply(d);
} break;
case mtpc_updateDeleteScheduledMessages: {
const auto &d = update.c_updateDeleteScheduledMessages();
session().data().scheduledMessages().apply(d);
session().scheduledMessages().apply(d);
} break;
case mtpc_updateQuickReplies: {
@@ -2610,6 +2622,11 @@ void Updates::feedUpdate(const MTPUpdate &update) {
_session->data().stories().apply(data.vstealth_mode());
} break;
case mtpc_updateStarsBalance: {
const auto &data = update.c_updateStarsBalance();
_session->setCredits(data.vbalance().v);
} break;
}
}
@@ -307,8 +307,8 @@ void UserPrivacy::reload(Key key) {
}
void UserPrivacy::pushPrivacy(Key key, const TLRules &rules) {
const auto &saved = (_privacyValues[key] =
TLToRules(rules, _session->data()));
const auto &saved
= (_privacyValues[key] = TLToRules(rules, _session->data()));
const auto i = _privacyChanges.find(key);
if (i != end(_privacyChanges)) {
i->second.fire_copy(saved);
+81 -16
View File
@@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_user_names.h"
#include "api/api_websites.h"
#include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/notify/data_notify_settings.h"
#include "data/data_changes.h"
#include "data/data_web_page.h"
@@ -43,13 +44,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_forum.h"
#include "data/data_saved_sublist.h"
#include "data/data_search_controller.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_chat_filters.h"
#include "data/data_histories.h"
#include "data/data_history_messages.h"
#include "core/core_cloud_password.h"
#include "core/application.h"
#include "base/unixtime.h"
@@ -291,6 +292,12 @@ void ApiWrap::topPromotionDone(const MTPhelp_PromoData &proxy) {
base::unixtime::now(),
_topPromotionNextRequestTime);
const auto settings = &AyuSettings::getInstance();
if (settings->disableAds) {
_session->data().setTopPromoted(nullptr, QString(), QString());
return;
}
proxy.match([&](const MTPDhelp_promoDataEmpty &data) {
_session->data().setTopPromoted(nullptr, QString(), QString());
}, [&](const MTPDhelp_promoData &data) {
@@ -559,7 +566,7 @@ void ApiWrap::sendMessageFail(
}
}
} else if (error == u"SCHEDULE_STATUS_PRIVATE"_q) {
auto &scheduled = _session->data().scheduledMessages();
auto &scheduled = _session->scheduledMessages();
Assert(peer->isUser());
if (const auto item = scheduled.lookupItem(peer->id, itemId.msg)) {
scheduled.removeSending(item);
@@ -813,7 +820,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
const auto storyId = story->fullId();
const auto peer = story->peer();
const auto fallback = [&] {
const auto base = peer->userName();
const auto base = peer->username();
const auto story = QString::number(storyId.story);
const auto query = base + "/s/" + story;
return session().createInternalLinkFull(query);
@@ -1573,8 +1580,8 @@ void ApiWrap::saveStickerSets(
writeRecent = true;
}
const auto isAttached =
(removedSetId == Data::Stickers::CloudRecentAttachedSetId);
const auto isAttached
= (removedSetId == Data::Stickers::CloudRecentAttachedSetId);
const auto flags = isAttached
? MTPmessages_ClearRecentStickers::Flag::f_attached
: MTPmessages_ClearRecentStickers::Flags(0);
@@ -2480,8 +2487,8 @@ void ApiWrap::refreshFileReference(
_session->data().peer(storyId.peer)->input,
MTP_vector<MTPint>(1, MTP_int(storyId.story))));
} else if (item->isScheduled()) {
const auto &scheduled = _session->data().scheduledMessages();
const auto realId = scheduled.lookupId(item);
const auto realId = _session->scheduledMessages().lookupId(
item);
request(MTPmessages_GetScheduledMessages(
item->history()->peer->input,
MTP_vector<MTPint>(1, MTP_int(realId))));
@@ -2527,8 +2534,8 @@ void ApiWrap::refreshFileReference(
}, [&](Data::FileOriginPeerPhoto data) {
fail();
}, [&](Data::FileOriginStickerSet data) {
const auto isRecentAttached =
(data.setId == Data::Stickers::CloudRecentAttachedSetId);
const auto isRecentAttached
= (data.setId == Data::Stickers::CloudRecentAttachedSetId);
if (data.setId == Data::Stickers::CloudRecentSetId
|| data.setId == Data::Stickers::RecentSetId
|| isRecentAttached) {
@@ -3111,6 +3118,46 @@ void ApiWrap::resolveJumpToHistoryDate(
}
}
void ApiWrap::requestHistory(
not_null<History*> history,
MsgId messageId,
SliceType slice) {
const auto peer = history->peer;
const auto key = HistoryRequest{
peer,
messageId,
slice,
};
if (_historyRequests.contains(key)) {
return;
}
const auto prepared = Api::PrepareHistoryRequest(peer, messageId, slice);
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::History;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
return request(
std::move(prepared)
).done([=](const Api::HistoryRequestResult &result) {
_historyRequests.remove(key);
auto parsed = Api::ParseHistoryResult(
peer,
messageId,
slice,
result);
history->messages().addSlice(
std::move(parsed.messageIds),
parsed.noSkipRange,
parsed.fullCount);
finish();
}).fail([=] {
_historyRequests.remove(key);
finish();
}).send();
});
_historyRequests.emplace(key);
}
void ApiWrap::requestSharedMedia(
not_null<PeerData*> peer,
MsgId topicRootId,
@@ -3382,6 +3429,9 @@ void ApiWrap::forwardMessages(
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
// forwarded messages don't have effects
//.effectId = action.options.effectId,
}, item);
_session->data().registerMessageRandomId(randomId, newId);
if (!localIds) {
@@ -3482,6 +3532,7 @@ void ApiWrap::sendSharedContact(
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
.effectId = action.options.effectId,
}, TextWithEntities(), MTP_messageMediaContact(
MTP_string(phone),
MTP_string(firstName),
@@ -3784,7 +3835,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
const auto anonymousPost = peer->amAnonymous();
const auto silentPost = ShouldSendSilent(peer, action.options);
FillMessagePostFlags(action, peer, flags);
if (exactWebPage && !ignoreWebPage && message.webPage.invert) {
if ((exactWebPage && !ignoreWebPage && message.webPage.invert)
|| action.options.invertCaption) {
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMessage::Flag::f_invert_media;
mediaFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
@@ -3830,6 +3882,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut;
mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
if (action.options.effectId) {
sendFlags |= MTPmessages_SendMessage::Flag::f_effect;
mediaFlags |= MTPmessages_SendMedia::Flag::f_effect;
}
lastMessage = history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
@@ -3838,6 +3894,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
.effectId = action.options.effectId,
}, sending, media);
const auto done = [=](
const MTPUpdates &result,
@@ -3885,7 +3942,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
sentEntities,
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
mtpShortcut
mtpShortcut,
MTP_long(action.options.effectId)
), done, fail);
} else {
histories.sendPreparedMessage(
@@ -3902,7 +3960,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
sentEntities,
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
mtpShortcut
mtpShortcut,
MTP_long(action.options.effectId)
), done, fail);
}
isFirst = false;
@@ -4185,7 +4244,9 @@ void ApiWrap::sendMediaWithRandomId(
| (!sentEntities.v.isEmpty() ? Flag::f_entities : Flag(0))
| (options.scheduled ? Flag::f_schedule_date : Flag(0))
| (options.sendAs ? Flag::f_send_as : Flag(0))
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0));
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0))
| (options.effectId ? Flag::f_effect : Flag(0))
| (options.invertCaption ? Flag::f_invert_media : Flag(0));
auto &histories = history->owner().histories();
const auto peer = history->peer;
@@ -4205,7 +4266,8 @@ void ApiWrap::sendMediaWithRandomId(
sentEntities,
MTP_int(options.scheduled),
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, options.shortcutId)
Data::ShortcutIdToMTP(_session, options.shortcutId),
MTP_long(options.effectId)
), [=](const MTPUpdates &result, const MTP::Response &response) {
if (done) done(true);
if (updateRecentStickers) {
@@ -4303,7 +4365,9 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
| (sendAs ? Flag::f_send_as : Flag(0))
| (album->options.shortcutId
? Flag::f_quick_reply_shortcut
: Flag(0));
: Flag(0))
| (album->options.effectId ? Flag::f_effect : Flag(0))
| (album->options.invertCaption ? Flag::f_invert_media : Flag(0));
auto &histories = history->owner().histories();
const auto peer = history->peer;
histories.sendPreparedMessage(
@@ -4317,7 +4381,8 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
MTP_vector<MTPInputSingleMedia>(medias),
MTP_int(album->options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, album->options.shortcutId)
Data::ShortcutIdToMTP(_session, album->options.shortcutId),
MTP_long(album->options.effectId)
), [=](const MTPUpdates &result, const MTP::Response &response) {
_sendingAlbums.remove(groupId);
+17 -1
View File
@@ -274,6 +274,10 @@ public:
Fn<void(not_null<PeerData*>, MsgId)> callback);
using SliceType = Data::LoadDirection;
void requestHistory(
not_null<History*> history,
MsgId messageId,
SliceType slice);
void requestSharedMedia(
not_null<PeerData*> peer,
MsgId topicRootId,
@@ -511,7 +515,8 @@ private:
not_null<PeerData*> peer,
bool justClear,
bool revoke);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result) const;
void applyAffectedMessages(
const MTPmessages_AffectedMessages &result) const;
void deleteAllFromParticipantSend(
not_null<ChannelData*> channel,
@@ -645,6 +650,17 @@ private:
};
base::flat_set<SharedMediaRequest> _sharedMediaRequests;
struct HistoryRequest {
not_null<PeerData*> peer;
MsgId aroundId = 0;
SliceType sliceType = {};
friend inline auto operator<=>(
const HistoryRequest&,
const HistoryRequest&) = default;
};
base::flat_set<HistoryRequest> _historyRequests;
std::unique_ptr<DialogsLoadState> _dialogsLoadState;
TimeId _dialogsLoadTill = 0;
rpl::variable<bool> _dialogsLoadMayBlockByDate = false;
-1
View File
@@ -29,7 +29,6 @@ void initLang() {
void initFonts() {
auto settings = &AyuSettings::getInstance();
AyuFonts::setMainFont(settings->mainFont);
AyuFonts::setMonoFont(settings->monoFont);
}
+8 -17
View File
@@ -195,6 +195,9 @@ AyuGramSettings::AyuGramSettings() {
saveDeletedMessages = true;
saveMessagesHistory = true;
// ~ Message filters
hideFromBlocked = false;
// ~ QoL toggles
disableAds = true;
disableStories = false;
@@ -202,11 +205,8 @@ AyuGramSettings::AyuGramSettings() {
collapseSimilarChannels = true;
hideSimilarChannels = false;
uploadSpeedBoost = false;
disableNotificationsDelay = false;
localPremium = false;
copyUsernameAsLink = true;
// ~ Customization
appIcon = AyuAssets::DEFAULT_ICON;
@@ -233,7 +233,6 @@ AyuGramSettings::AyuGramSettings() {
showGhostToggleInTray = true;
showStreamerToggleInTray = false;
mainFont = "";
monoFont = "";
hideNotificationCounters = false;
@@ -243,7 +242,7 @@ AyuGramSettings::AyuGramSettings() {
* showPeerId = 0 means no ID shown
* showPeerId = 1 means ID shown as for Telegram API devs
* showPeerId = 2 means ID shown as for Bot API devs (-100)
*/
*/
showPeerId = 2;
showMessageSeconds = false;
showMessageShot = true;
@@ -309,6 +308,10 @@ void AyuGramSettings::set_saveMessagesHistory(bool val) {
saveMessagesHistory = val;
}
void AyuGramSettings::set_hideFromBlocked(bool val) {
hideFromBlocked = val;
}
void AyuGramSettings::set_disableAds(bool val) {
disableAds = val;
}
@@ -329,10 +332,6 @@ void AyuGramSettings::set_hideSimilarChannels(bool val) {
hideSimilarChannels = val;
}
void AyuGramSettings::set_uploadSpeedBoost(bool val) {
uploadSpeedBoost = val;
}
void AyuGramSettings::set_disableNotificationsDelay(bool val) {
disableNotificationsDelay = val;
}
@@ -341,10 +340,6 @@ void AyuGramSettings::set_localPremium(bool val) {
localPremium = val;
}
void AyuGramSettings::set_copyUsernameAsLink(bool val) {
copyUsernameAsLink = val;
}
void AyuGramSettings::set_appIcon(QString val) {
appIcon = std::move(val);
}
@@ -411,10 +406,6 @@ void AyuGramSettings::set_showStreamerToggleInTray(bool val) {
showStreamerToggleInTray = val;
}
void AyuGramSettings::set_mainFont(QString val) {
mainFont = val;
}
void AyuGramSettings::set_monoFont(QString val) {
monoFont = val;
}
+5 -11
View File
@@ -29,17 +29,16 @@ public:
bool saveDeletedMessages;
bool saveMessagesHistory;
bool hideFromBlocked;
bool disableAds;
bool disableStories;
bool disableCustomBackgrounds;
bool collapseSimilarChannels;
bool hideSimilarChannels;
bool uploadSpeedBoost;
bool disableNotificationsDelay;
bool localPremium;
bool copyUsernameAsLink;
QString appIcon;
bool simpleQuotesAndReplies;
@@ -61,7 +60,6 @@ public:
bool showGhostToggleInTray;
bool showStreamerToggleInTray;
QString mainFont;
QString monoFont;
bool hideNotificationCounters;
@@ -89,17 +87,16 @@ public:
void set_saveDeletedMessages(bool val);
void set_saveMessagesHistory(bool val);
void set_hideFromBlocked(bool val);
void set_disableAds(bool val);
void set_disableStories(bool val);
void set_disableCustomBackgrounds(bool val);
void set_collapseSimilarChannels(bool val);
void set_hideSimilarChannels(bool val);
void set_uploadSpeedBoost(bool val);
void set_disableNotificationsDelay(bool val);
void set_localPremium(bool val);
void set_copyUsernameAsLink(bool val);
void set_appIcon(QString val);
void set_simpleQuotesAndReplies(bool val);
@@ -121,7 +118,6 @@ public:
void set_showGhostToggleInTray(bool val);
void set_showStreamerToggleInTray(bool val);
void set_mainFont(QString val);
void set_monoFont(QString val);
void set_hideNotificationCounters(bool val);
@@ -147,15 +143,14 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
useScheduledMessages,
saveDeletedMessages,
saveMessagesHistory,
hideFromBlocked,
disableAds,
disableStories,
disableCustomBackgrounds,
collapseSimilarChannels,
hideSimilarChannels,
uploadSpeedBoost,
disableNotificationsDelay,
localPremium,
copyUsernameAsLink,
appIcon,
simpleQuotesAndReplies,
deletedMark,
@@ -172,7 +167,6 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
showStreamerToggleInDrawer,
showGhostToggleInTray,
showStreamerToggleInTray,
mainFont,
monoFont,
hideNotificationCounters,
hideAllChatsFolder,
File diff suppressed because it is too large Load Diff
+22 -3
View File
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.45.0"
#define SQLITE_VERSION_NUMBER 3045000
#define SQLITE_SOURCE_ID "2024-01-15 17:01:13 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d"
#define SQLITE_VERSION "3.45.3"
#define SQLITE_VERSION_NUMBER 3045003
#define SQLITE_SOURCE_ID "2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not dereference the arrays or string pointers
** passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(
@@ -2141,6 +2143,22 @@ struct sqlite3_mem_methods {
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
** compile-time option is not set, then the default maximum is 1073741824.
**
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
** defaults to on. This configuration option queries the current setting or
** changes the setting to off or on. The argument is a pointer to an integer.
** If that integer initially holds a value of 1, then the ability for VIEWs to
** have ROWIDs is activated. If the integer initially holds zero, then the
** ability is deactivated. Any other initial value for the integer leaves the
** setting unchanged. After changes, if any, the integer is written with
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
** recommended case) then the integer is always filled with zero, regardless
** if its initial value.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2172,6 +2190,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -665,7 +665,7 @@ void Content::setupContent(
const std::vector<Font> &fonts) {
using namespace rpl::mappers;
const auto current = AyuFonts::getMainFont();
const auto current = AyuFonts::getMonoFont();
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
const auto add = [&](const std::vector<Font> &list)
{
@@ -1,66 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2024
#include "server_read_confirmation_box.h"
#include "lang_auto.h"
#include "ayu/ayu_settings.h"
#include "ayu/utils/telegram_helpers.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "styles/style_layers.h"
#include "window/window_session_controller.h"
namespace AyuUi {
ServerReadConfirmationBox::ServerReadConfirmationBox(
QWidget *,
not_null<Window::SessionController*> controller)
: _controller(controller) {
//
}
void ServerReadConfirmationBox::prepare() {
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
auto fullHeight = st::boxPadding.top()
+ _text->height()
+ st::boxPadding.bottom();
setDimensions(st::boxWidth, fullHeight);
addButton(tr::ayu_ReadConfirmationBoxActionText(),
[=, this]
{
ReadAllPeers();
closeBox();
});
addButton(tr::lng_cancel(),
[=, this]
{
closeBox();
});
}
void ServerReadConfirmationBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
const auto &padding = st::boxPadding;
_text->moveToLeft(padding.left(), padding.top());
}
void ServerReadConfirmationBox::ReadAllPeers() {
auto settings = &AyuSettings::getInstance();
auto prev = settings->sendReadMessages;
settings->set_sendReadMessages(true);
auto chats = _controller->session().data().chatsList();
MarkAsReadChatList(chats);
settings->set_sendReadMessages(prev);
}
}
@@ -1,31 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2024
#pragma once
#include "ui/layers/box_content.h"
#include "window/window_main_menu.h"
namespace AyuUi {
class ServerReadConfirmationBox : public Ui::BoxContent
{
public:
ServerReadConfirmationBox(QWidget *, not_null<Window::SessionController*> controller);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private:
void ReadAllPeers();
not_null<Window::SessionController*> _controller;
object_ptr<Ui::FlatLabel> _text = {nullptr};
};
}
@@ -27,6 +27,7 @@
#include "ayu/ui/sections/edited/edited_log_section.h"
#include "ayu/utils/telegram_helpers.h"
#include "base/unixtime.h"
#include "history/view/history_view_context_menu.h"
#include "history/view/history_view_element.h"
#include "window/window_session_controller.h"
@@ -54,6 +55,10 @@ void AddHideMessageAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
return;
}
if (item->history()->peer->isSelf()) {
return;
}
const auto history = item->history();
menu->addAction(tr::ayu_ContextHideMessage(tr::now),
[=]()
@@ -73,22 +78,23 @@ 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(QString(), key, item->from()->asUser());
}
}
},
&st::menuIconTTL);
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(QString(), key, item->from()->asUser());
}
}
},
&st::menuIconTTL);
}
}
@@ -108,6 +114,22 @@ void AddMessageDetailsAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
const auto media = item->media();
const auto isSticker = media && media->document() && media->document()->sticker();
const auto emojiPacks = HistoryView::CollectEmojiPacks(item, HistoryView::EmojiPacksSource::Message);
auto containsSingleCustomEmojiPack = emojiPacks.size() == 1;
if (!containsSingleCustomEmojiPack && emojiPacks.size() > 1) {
const auto author = emojiPacks.front().id >> 32;
auto sameAuthor = true;
for (const auto pack : emojiPacks) {
if (pack.id >> 32 != author) {
sameAuthor = false;
break;
}
}
containsSingleCustomEmojiPack = sameAuthor;
}
const auto isForwarded = forwarded && !forwarded->story && forwarded->psaType.isEmpty();
const auto messageId = QString::number(item->id.bare);
@@ -274,12 +296,28 @@ void AddMessageDetailsAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
}
}
}
if (containsSingleCustomEmojiPack) {
const auto authorId = emojiPacks.front().id >> 32;
if (authorId != 0) {
menu2->addAction(Ui::ContextActionStickerAuthor(
menu2->menu(),
&item->history()->session(),
authorId
));
}
}
},
});
}
void AddReadUntilAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
if (item->isLocal()) {
if (item->isLocal() || item->isService()) {
return;
}
if (item->history()->peer->isSelf()) {
return;
}
@@ -610,13 +610,18 @@ void InnerWidget::elementStartInteraction(not_null<const Element*> view) {
}
void InnerWidget::elementStartPremium(
not_null<const Element*> view,
Element *replacing) {
not_null<const HistoryView::Element*> view,
HistoryView::Element *replacing) {
}
void InnerWidget::elementCancelPremium(not_null<const Element*> view) {
}
void InnerWidget::elementStartEffect(
not_null<const Element*> view,
Element *replacing) {
}
QString InnerWidget::elementAuthorRank(not_null<const Element*> view) {
return {};
}
@@ -127,10 +127,11 @@ public:
void elementStartPremium(
not_null<const HistoryView::Element*> view,
HistoryView::Element *replacing) override;
void elementCancelPremium(
not_null<const HistoryView::Element*> view) override;
QString elementAuthorRank(
not_null<const HistoryView::Element*> view) override;
void elementCancelPremium(not_null<const HistoryView::Element*> view) override;
void elementStartEffect(
not_null<const HistoryView::Element*> view,
HistoryView::Element *replacing) override;
QString elementAuthorRank(not_null<const HistoryView::Element*> view) override;
~InnerWidget();
@@ -381,7 +381,7 @@ auto GenerateParticipantString(
data,
});
}
const auto username = peer->userName();
const auto username = peer->username();
if (username.isEmpty()) {
return name;
}
@@ -33,18 +33,19 @@ const QVector<QString> icons{
const auto rows = static_cast<int>(icons.size()) / 4 + std::min(1, static_cast<int>(icons.size()) % 4);
void drawIcon(QPainter &p, const QImage &icon, int xOffset, int yOffset, bool selected) {
void drawIcon(QPainter &p, const QImage &icon, int xOffset, int yOffset, float strokeOpacity) {
xOffset += st::cpPadding;
if (selected) {
p.save();
p.setPen(QPen(st::iconPreviewStroke, st::cpPenSize));
p.drawEllipse(xOffset + st::cpSelectedPadding,
yOffset + st::cpSelectedPadding,
st::cpIconSize + st::cpSelectedPadding * 2,
st::cpIconSize + st::cpSelectedPadding * 2);
p.restore();
}
// stroke
p.save();
p.setPen(QPen(st::iconPreviewStroke, st::cpPenSize));
p.setOpacity(strokeOpacity);
p.drawEllipse(xOffset + st::cpSelectedPadding,
yOffset + st::cpSelectedPadding,
st::cpIconSize + st::cpSelectedPadding * 2,
st::cpIconSize + st::cpSelectedPadding * 2);
p.restore();
// /stroke
auto rect = QRect(xOffset + st::cpImagePadding, yOffset + st::cpImagePadding, st::cpIconSize, st::cpIconSize);
p.drawImage(rect, icon);
@@ -81,11 +82,19 @@ void IconPicker::paintEvent(QPaintEvent *e) {
const auto &iconName = icons[idx];
auto icon = AyuAssets::loadPreview(iconName)
.scaled(st::cpIconSize, st::cpIconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
auto opacity = 0.0f;
if (iconName == wasSelected) {
opacity = 1.0f - animation.value(1.0f);
} else if (iconName == AyuAssets::currentAppLogoName()) {
opacity = wasSelected.isEmpty() ? 1.0f : animation.value(1.0f);
}
drawIcon(p,
icon,
(st::cpIconSize + st::cpSpacingX) * i + offset,
row * (st::cpIconSize + st::cpSpacingY),
AyuAssets::currentAppLogoName() == iconName);
opacity);
}
}
}
@@ -106,6 +115,17 @@ void IconPicker::mousePressEvent(QMouseEvent *e) {
&& e->pos().y() <= yOffset + st::cpIconSize) {
const auto &iconName = icons[idx];
if (settings->appIcon != iconName) {
wasSelected = settings->appIcon;
animation.start(
[=]
{
update();
},
0.0,
1.0,
200,
anim::easeOutCubic);
settings->set_appIcon(iconName);
changed = true;
break;
@@ -7,6 +7,7 @@
#pragma once
#include "ui/rp_widget.h"
#include "ui/effects/animations.h"
class IconPicker : public Ui::RpWidget
{
@@ -16,4 +17,7 @@ public:
protected:
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
Ui::Animations::Simple animation;
QString wasSelected;
};
@@ -563,6 +563,31 @@ void SetupSpyEssentials(not_null<Ui::VerticalLayout*> container) {
container->lifetime());
}
void SetupMessageFilters(not_null<Ui::VerticalLayout*> container) {
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_RegexFilters());
AddButtonWithIcon(
container,
tr::ayu_FiltersHideFromBlocked(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->hideFromBlocked)
)->toggledValue(
) | rpl::filter(
[=](bool enabled)
{
return (enabled != settings->hideFromBlocked);
}) | start_with_next(
[=](bool enabled)
{
settings->set_hideFromBlocked(enabled);
AyuSettings::save();
},
container->lifetime());
}
void SetupQoLToggles(not_null<Ui::VerticalLayout*> container) {
auto settings = &AyuSettings::getInstance();
@@ -667,29 +692,6 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
AddButtonWithIcon(
container,
tr::ayu_UploadSpeedBoostPC(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->uploadSpeedBoost)
)->toggledValue(
) | rpl::filter(
[=](bool enabled)
{
return (enabled != settings->uploadSpeedBoost);
}) | start_with_next(
[=](bool enabled)
{
settings->set_uploadSpeedBoost(enabled);
AyuSettings::save();
},
container->lifetime());
AddSkip(container);
AddDivider(container);
AddSkip(container);
AddButtonWithIcon(
container,
tr::ayu_DisableNotificationsDelay(),
@@ -727,25 +729,6 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout*> container) {
AyuSettings::save();
},
container->lifetime());
AddButtonWithIcon(
container,
tr::ayu_CopyUsernameAsLink(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->copyUsernameAsLink)
)->toggledValue(
) | rpl::filter(
[=](bool enabled)
{
return (enabled != settings->copyUsernameAsLink);
}) | start_with_next(
[=](bool enabled)
{
settings->set_copyUsernameAsLink(enabled);
AyuSettings::save();
},
container->lifetime());
}
void SetupAppIcon(not_null<Ui::VerticalLayout*> container) {
@@ -1031,7 +1014,7 @@ void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout*> container) {
st::autoDownloadLimitSlider,
st::settingsScaleLabel,
0,
st::settingsScaleLabel.style.font->width("30%"));
st::settingsScaleLabel.style.font->width("8%%"));
container->add(std::move(recentStickersLimitSlider.widget), st::recentStickersLimitPadding);
const auto slider = recentStickersLimitSlider.slider;
const auto label = recentStickersLimitSlider.label;
@@ -1066,28 +1049,6 @@ void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout*> container) {
void SetupFonts(not_null<Ui::VerticalLayout*> container, not_null<Window::SessionController*> controller) {
const auto settings = &AyuSettings::getInstance();
const auto commonButton = AddButtonWithLabel(
container,
tr::ayu_MainFont(),
rpl::single(
settings->mainFont.isEmpty() ? tr::ayu_FontDefault(tr::now) : settings->mainFont
),
st::settingsButtonNoIcon);
const auto commonGuard = Ui::CreateChild<base::binary_guard>(commonButton.get());
commonButton->addClickHandler(
[=]
{
*commonGuard = AyuUi::FontSelectorBox::Show(controller,
[=](QString font)
{
auto ayuSettings = &AyuSettings::getInstance();
ayuSettings->set_mainFont(std::move(font));
AyuSettings::save();
});
});
const auto monoButton = AddButtonWithLabel(
container,
tr::ayu_MonospaceFont(),
@@ -1340,6 +1301,12 @@ void SetupAyuGramSettings(not_null<Ui::VerticalLayout*> container,
AddDivider(container);
AddSkip(container);
SetupMessageFilters(container);
AddSkip(container);
AddDivider(container);
AddSkip(container);
SetupQoLToggles(container);
AddSkip(container);
@@ -1354,7 +1321,6 @@ void SetupAyuGramSettings(not_null<Ui::VerticalLayout*> container,
AddSkip(container);
SetupSendConfirmations(container);
AddSkip(container);
AddDivider(container);
AddDividerText(container, tr::ayu_SettingsWatermark());
}
@@ -29,12 +29,14 @@
#include "data/data_session.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
#include "history/history_unread_things.h"
#include "main/main_account.h"
#include "main/main_session.h"
#include "ui/text/format_values.h"
#include "ayu/ayu_settings.h"
#include "ayu/ayu_state.h"
// https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java
std::unordered_set<ID> ayugram_channels = {
@@ -160,6 +162,31 @@ bool isExteraRelated(ID peerId) {
return extera_devs.contains(peerId) || extera_channels.contains(peerId);
}
bool isMessageHidden(const not_null<HistoryItem*> item) {
if (AyuState::isHidden(item)) {
return true;
}
const auto settings = &AyuSettings::getInstance();
if (settings->hideFromBlocked) {
if (item->from()->isUser() &&
item->from()->asUser()->isBlocked()) {
// don't hide messages if it's a dialog with blocked user
return item->from()->asUser()->id != item->history()->peer->id;
}
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
if (forwarded->originalSender &&
forwarded->originalSender->isUser() &&
forwarded->originalSender->asUser()->isBlocked()) {
return true;
}
}
}
return false;
}
void MarkAsReadChatList(not_null<Dialogs::MainList*> list) {
auto mark = std::vector<not_null<History*>>();
for (const auto &row : list->indexed()->all()) {
@@ -223,7 +250,7 @@ void readReactions(base::weak_ptr<Data::Thread> weakThread) {
}
void MarkAsReadThread(not_null<Data::Thread*> thread) {
const auto readHistory = [&](not_null<History*> history)
const auto readHistoryNative = [&](not_null<History*> history)
{
history->owner().histories().readInbox(history);
};
@@ -245,13 +272,13 @@ void MarkAsReadThread(not_null<Data::Thread*> thread) {
{
MarkAsReadThread(topic);
});
} else if (const auto history = thread->asHistory()) {
readHistory(history);
if (const auto migrated = history->migrateSibling()) {
readHistory(migrated);
}
} else if (const auto topic = thread->asTopic()) {
topic->readTillEnd();
} else if (const auto history = thread->asHistory()) {
readHistoryNative(history);
if (const auto migrated = history->migrateSibling()) {
readHistoryNative(migrated);
}
}
}
@@ -492,11 +519,7 @@ QString getMediaDC(not_null<HistoryItem*> message) {
int getScheduleTime(int64 sumSize) {
auto time = 12;
const auto settings = &AyuSettings::getInstance();
const auto multiplier = settings->uploadSpeedBoost ? 0.7 : 4.5;
time += (int) std::ceil(std::max(6.0, std::ceil(sumSize / 1024.0 / 1024.0 * multiplier))) + 1;
time += (int) std::ceil(std::max(6.0, std::ceil(sumSize / 1024.0 / 1024.0 * 0.7))) + 1;
return time;
}
@@ -25,6 +25,8 @@ ID getBareID(not_null<PeerData*> peer);
bool isAyuGramRelated(ID peerId);
bool isExteraRelated(ID peerId);
bool isMessageHidden(not_null<HistoryItem*> item);
void MarkAsReadChatList(not_null<Dialogs::MainList*> list);
void MarkAsReadThread(not_null<Data::Thread*> thread);
+20 -12
View File
@@ -192,20 +192,27 @@ void ShowAddParticipantsError(
&& channel
&& !channel->isMegagroup()
&& channel->canAddAdmins()) {
const auto makeAdmin = [=] {
const auto makeAdmin = [=](Fn<void()> close) {
const auto user = forbidden.users.front();
const auto weak = std::make_shared<QPointer<EditAdminBox>>();
const auto close = [=](auto&&...) {
if (*weak) {
(*weak)->closeBox();
const auto done = [=](auto&&...) {
if (const auto strong = weak->data()) {
strong->uiShow()->showToast(
tr::lng_box_done(tr::now));
strong->closeBox();
}
};
const auto fail = [=] {
if (const auto strong = weak->data()) {
strong->closeBox();
}
};
const auto saveCallback = SaveAdminCallback(
show,
channel,
user,
close,
close);
done,
fail);
auto box = Box<EditAdminBox>(
channel,
user,
@@ -214,6 +221,7 @@ void ShowAddParticipantsError(
box->setSaveCallback(saveCallback);
*weak = box.data();
show->showBox(std::move(box));
close();
};
show->showBox(
Ui::MakeConfirmBox({
@@ -605,8 +613,8 @@ void GroupInfoBox::prepare() {
_navigation->session().api().selfDestruct().reload();
const auto top = addTopButton(st::infoTopBarMenu);
const auto menu =
top->lifetime().make_state<base::unique_qptr<Ui::PopupMenu>>();
const auto menu
= top->lifetime().make_state<base::unique_qptr<Ui::PopupMenu>>();
top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>(
top,
@@ -1306,8 +1314,8 @@ void SetupChannelBox::handleChange() {
&& (ch < 'a' || ch > 'z')
&& (ch < '0' || ch > '9')
&& ch != '_') {
const auto badSymbols =
tr::lng_create_channel_link_bad_symbols(tr::now);
const auto badSymbols
= tr::lng_create_channel_link_bad_symbols(tr::now);
if (_errorText != badSymbols) {
_errorText = badSymbols;
update();
@@ -1317,8 +1325,8 @@ void SetupChannelBox::handleChange() {
}
}
if (name.size() < Ui::EditPeer::kMinUsernameLength) {
const auto tooShort =
tr::lng_create_channel_link_too_short(tr::now);
const auto tooShort
= tr::lng_create_channel_link_too_short(tr::now);
if (_errorText != tooShort) {
_errorText = tooShort;
update();
@@ -593,11 +593,11 @@ void BackgroundPreviewBox::uploadForPeer(bool both) {
const auto ready = Window::Theme::PrepareWallPaper(
session->mainDcId(),
_paper.localThumbnail()->original());
const auto documentId = ready.id;
const auto documentId = ready->id;
_uploadId = FullMsgId(
session->userPeerId(),
session->data().nextLocalMessageId());
session->uploader().uploadMedia(_uploadId, ready);
session->uploader().upload(_uploadId, ready);
if (_uploadLifetime) {
return;
}
@@ -940,7 +940,7 @@ int BackgroundPreviewBox::textsTop() const {
- st::historyPaddingBottom
- (_service ? _service->height() : 0)
- _text1->height()
- (forChannel() ? _text2->height() : 0);
- (forChannel() ? 0 : _text2->height());
}
QRect BackgroundPreviewBox::radialRect() const {
+61 -2
View File
@@ -546,7 +546,7 @@ rightsToggle: Toggle(defaultToggle) {
vsize: 0px;
vshift: 1px;
stroke: 2px;
duration: 120;
duration: universalDuration;
}
rightsButton: SettingsButton(defaultSettingsButton) {
@@ -642,6 +642,10 @@ proxyDropdownUpPosition: point(-2px, 20px);
proxyAboutPadding: margins(22px, 7px, 22px, 14px);
proxyAboutSponsorPadding: margins(22px, 7px, 22px, 0px);
proxyApplyBoxLabel : FlatLabel(defaultFlatLabel) {
maxHeight: 30px;
}
markdownLinkFieldPadding: margins(22px, 0px, 22px, 10px);
termsContent: FlatLabel(defaultFlatLabel) {
@@ -691,6 +695,10 @@ createPollOptionField: InputField(createPollField) {
placeholderMargins: margins(2px, 0px, 2px, 0px);
heightMax: 68px;
}
createPollOptionFieldPremium: InputField(createPollOptionField) {
textMargins: margins(22px, 11px, 68px, 11px);
}
createPollOptionFieldPremiumEmojiPosition: point(15px, -1px);
createPollSolutionField: InputField(createPollField) {
textMargins: margins(0px, 4px, 0px, 4px);
border: 1px;
@@ -704,7 +712,7 @@ createPollOptionRemove: CrossButton {
cross: CrossAnimation {
size: 22px;
skip: 6px;
stroke: 1.;
stroke: 1.5;
minScale: 0.3;
}
crossFg: boxTitleCloseFg;
@@ -718,6 +726,7 @@ createPollOptionRemove: CrossButton {
}
}
createPollOptionRemovePosition: point(11px, 9px);
createPollOptionEmojiPositionSkip: 4px;
createPollWarning: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;
palette: TextPalette(defaultTextPalette) {
@@ -1044,3 +1053,53 @@ inviteForbiddenTitle: FlatLabel(boxTitle) {
inviteForbiddenTitlePadding: margins(32px, 4px, 32px, 0px);
inviteForbiddenLockBg: dialogsUnreadBgMuted;
inviteForbiddenLockIcon: icon {{ "emoji/premium_lock", dialogsUnreadFg }};
collectibleIconDiameter: 72px;
collectibleIcon: 64px;
collectibleIconPadding: margins(24px, 32px, 24px, 12px);
collectibleHeader: FlatLabel(boxTitle) {
minWidth: 120px;
maxHeight: 0px;
align: align(top);
}
collectibleHeaderPadding: margins(24px, 16px, 24px, 12px);
collectibleOwnerPadding: margins(24px, 4px, 24px, 8px);
collectibleInfo: inviteForbiddenInfo;
collectibleInfoPadding: margins(24px, 12px, 24px, 12px);
collectibleInfoTonMargins: margins(0px, 3px, 0px, 0px);
collectibleMore: RoundButton(defaultActiveButton) {
height: 36px;
textTop: 9px;
radius: 6px;
}
collectibleMorePadding: margins(24px, 12px, 24px, 0px);
collectibleCopy: RoundButton(defaultLightButton) {
height: 36px;
textTop: 9px;
radius: 6px;
}
collectibleBox: Box(defaultBox) {
buttonPadding: margins(24px, 12px, 24px, 12px);
buttonHeight: 36px;
button: collectibleCopy;
}
moderateBoxUserpic: UserpicButton(defaultUserpicButton) {
size: size(34px, 42px);
photoSize: 34px;
photoPosition: point(0px, 4px);
}
moderateBoxExpand: icon {{ "chat/reply_type_group", boxTextFg }};
moderateBoxExpandHeight: 20px;
moderateBoxExpandRight: 10px;
moderateBoxExpandInnerSkip: 2px;
moderateBoxExpandFont: font(11px);
moderateBoxExpandToggleSize: 4px;
moderateBoxExpandToggleFourStrokes: 3px;
moderateBoxExpandIcon: icon{{ "info/edit/expand_arrow_small-flip_vertical", windowActiveTextFg }};
moderateBoxExpandIconDown: icon{{ "info/edit/expand_arrow_small", windowActiveTextFg }};
moderateBoxDividerLabel: FlatLabel(boxDividerLabel) {
palette: TextPalette(defaultTextPalette) {
selectLinkFg: windowActiveTextFg;
}
}
+183 -68
View File
@@ -7,32 +7,37 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/connection_box.h"
#include "ui/boxes/confirm_box.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "base/qthelp_url.h"
#include "base/call_delayed.h"
#include "base/qthelp_regex.h"
#include "base/qthelp_url.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/local_url_handlers.h"
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "mtproto/facade.h"
#include "ui/widgets/checkbox.h"
#include "storage/localstorage.h"
#include "ui/basic_click_handlers.h"
#include "ui/boxes/confirm_box.h"
#include "ui/effects/animations.h"
#include "ui/effects/radial_animation.h"
#include "ui/painter.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/widgets/fields/number_input.h"
#include "ui/widgets/fields/password_input.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/popup_menu.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/toast/toast.h"
#include "ui/effects/animations.h"
#include "ui/effects/radial_animation.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/basic_click_handlers.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "boxes/abstract_box.h" // Ui::show().
#include "window/window_session_controller.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
@@ -48,6 +53,22 @@ constexpr auto kSaveSettingsDelayedTimeout = crl::time(1000);
using ProxyData = MTP::ProxyData;
[[nodiscard]] ProxyData ProxyDataFromFields(
ProxyData::Type type,
const QMap<QString, QString> &fields) {
auto proxy = ProxyData();
proxy.type = type;
proxy.host = fields.value(u"server"_q);
proxy.port = fields.value(u"port"_q).toUInt();
if (type == ProxyData::Type::Socks5) {
proxy.user = fields.value(u"user"_q);
proxy.password = fields.value(u"pass"_q);
} else if (type == ProxyData::Type::Mtproto) {
proxy.password = fields.value(u"secret"_q);
}
return proxy;
};
class HostInput : public Ui::MaskedInputField {
public:
HostInput(
@@ -203,6 +224,7 @@ protected:
private:
void setupContent();
void setupTopButton();
void createNoRowsLabel();
void addNewProxy();
void applyView(View &&view);
@@ -600,9 +622,80 @@ void ProxiesBox::prepare() {
addButton(tr::lng_proxy_add(), [=] { addNewProxy(); });
addButton(tr::lng_close(), [=] { closeBox(); });
setupTopButton();
setupContent();
}
void ProxiesBox::setupTopButton() {
const auto top = addTopButton(st::infoTopBarMenu);
const auto menu
= top->lifetime().make_state<base::unique_qptr<Ui::PopupMenu>>();
const auto callback = [=] {
const auto maybeUrl = QGuiApplication::clipboard()->text();
const auto local = Core::TryConvertUrlToLocal(maybeUrl);
const auto proxyString = u"proxy"_q;
const auto socksString = u"socks"_q;
const auto protocol = u"tg://"_q;
const auto command = base::StringViewMid(
local,
protocol.size(),
8192);
if (local.startsWith(protocol + proxyString)
|| local.startsWith(protocol + socksString)) {
using namespace qthelp;
const auto options = RegExOption::CaseInsensitive;
for (const auto &[expression, _] : Core::LocalUrlHandlers()) {
const auto midExpression = base::StringViewMid(
expression,
1);
const auto isSocks = midExpression.startsWith(
socksString);
if (!midExpression.startsWith(proxyString)
&& !isSocks) {
continue;
}
const auto match = regex_match(
expression,
command,
options);
if (!match) {
continue;
}
const auto type = isSocks
? ProxyData::Type::Socks5
: ProxyData::Type::Mtproto;
const auto fields = url_parse_params(
match->captured(1),
qthelp::UrlParamNameTransform::ToLower);
const auto proxy = ProxyDataFromFields(type, fields);
const auto contains = _controller->contains(proxy);
const auto toast = (contains
? tr::lng_proxy_add_from_clipboard_existing_toast
: tr::lng_proxy_add_from_clipboard_good_toast)(tr::now);
uiShow()->showToast(toast);
if (!contains) {
_controller->addNewItem(proxy);
}
break;
}
} else {
uiShow()->showToast(
tr::lng_proxy_add_from_clipboard_failed_toast(tr::now));
}
};
top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>(top, st::defaultPopupMenu);
(*menu)->addAction(
tr::lng_proxy_add_from_clipboard(tr::now),
callback);
(*menu)->popup(QCursor::pos());
return true;
});
}
void ProxiesBox::setupContent() {
const auto inner = setInnerWidget(object_ptr<Ui::VerticalLayout>(this));
@@ -1094,70 +1187,84 @@ ProxiesBoxController::ProxiesBoxController(not_null<Main::Account*> account)
}
void ProxiesBoxController::ShowApplyConfirmation(
Window::SessionController *controller,
Type type,
const QMap<QString, QString> &fields) {
const auto server = fields.value(u"server"_q);
const auto port = fields.value(u"port"_q).toUInt();
auto proxy = ProxyData();
proxy.type = type;
proxy.host = server;
proxy.port = port;
if (type == Type::Socks5) {
proxy.user = fields.value(u"user"_q);
proxy.password = fields.value(u"pass"_q);
} else if (type == Type::Mtproto) {
proxy.password = fields.value(u"secret"_q);
const auto proxy = ProxyDataFromFields(type, fields);
if (!proxy) {
auto box = Ui::MakeInformBox(
(proxy.status() == ProxyData::Status::Unsupported
? tr::lng_proxy_unsupported(tr::now)
: tr::lng_proxy_invalid(tr::now)));
if (controller) {
controller->uiShow()->showBox(std::move(box));
} else {
Ui::show(std::move(box));
}
return;
}
if (proxy) {
static const auto UrlStartRegExp = QRegularExpression(
"^https://",
QRegularExpression::CaseInsensitiveOption);
static const auto UrlEndRegExp = QRegularExpression("/$");
const auto displayed = "https://" + server + "/";
const auto parsed = QUrl::fromUserInput(displayed);
const auto displayUrl = !UrlClickHandler::IsSuspicious(displayed)
? displayed
: parsed.isValid()
? QString::fromUtf8(parsed.toEncoded())
: UrlClickHandler::ShowEncoded(displayed);
const auto displayServer = QString(
displayUrl
).replace(
UrlStartRegExp,
QString()
).replace(UrlEndRegExp, QString());
const auto text = tr::lng_sure_enable_socks(
tr::now,
lt_server,
displayServer,
lt_port,
QString::number(port))
+ (proxy.type == Type::Mtproto
? "\n\n" + tr::lng_proxy_sponsor_warning(tr::now)
: QString());
auto callback = [=](Fn<void()> &&close) {
static const auto UrlStartRegExp = QRegularExpression(
"^https://",
QRegularExpression::CaseInsensitiveOption);
static const auto UrlEndRegExp = QRegularExpression("/$");
const auto displayed = "https://" + proxy.host + "/";
const auto parsed = QUrl::fromUserInput(displayed);
const auto displayUrl = !UrlClickHandler::IsSuspicious(displayed)
? displayed
: parsed.isValid()
? QString::fromUtf8(parsed.toEncoded())
: UrlClickHandler::ShowEncoded(displayed);
const auto displayServer = QString(
displayUrl
).replace(
UrlStartRegExp,
QString()
).replace(UrlEndRegExp, QString());
const auto box = [=](not_null<Ui::GenericBox*> box) {
box->setTitle(tr::lng_proxy_box_title());
if (type == Type::Mtproto) {
box->addRow(object_ptr<Ui::FlatLabel>(
box,
tr::lng_proxy_sponsor_warning(),
st::boxDividerLabel));
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
}
const auto &stL = st::proxyApplyBoxLabel;
const auto &stSubL = st::boxDividerLabel;
const auto add = [&](const QString &s, tr::phrase<> phrase) {
if (!s.isEmpty()) {
box->addRow(object_ptr<Ui::FlatLabel>(box, s, stL));
box->addRow(object_ptr<Ui::FlatLabel>(box, phrase(), stSubL));
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
}
};
if (!displayServer.isEmpty()) {
add(displayServer, tr::lng_proxy_box_server);
}
add(QString::number(proxy.port), tr::lng_proxy_box_port);
if (type == Type::Socks5) {
add(proxy.user, tr::lng_proxy_box_username);
add(proxy.password, tr::lng_proxy_box_password);
} else if (type == Type::Mtproto) {
add(proxy.password, tr::lng_proxy_box_secret);
}
box->addButton(tr::lng_sure_enable(), [=] {
auto &proxies = Core::App().settings().proxy().list();
if (!ranges::contains(proxies, proxy)) {
proxies.push_back(proxy);
}
Core::App().setCurrentProxy(
proxy,
ProxyData::Settings::Enabled);
Core::App().setCurrentProxy(proxy, ProxyData::Settings::Enabled);
Local::writeSettings();
close();
};
Ui::show(
Ui::MakeConfirmBox({
.text = text,
.confirmed = std::move(callback),
.confirmText = tr::lng_sure_enable(),
}),
Ui::LayerOption::KeepOther);
box->closeBox();
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
};
if (controller) {
controller->uiShow()->showBox(Box(box));
} else {
Ui::show(Ui::MakeInformBox(
(proxy.status() == ProxyData::Status::Unsupported
? tr::lng_proxy_unsupported(tr::now)
: tr::lng_proxy_invalid(tr::now))));
Ui::show(Box(box));
}
}
@@ -1448,6 +1555,14 @@ object_ptr<Ui::BoxContent> ProxiesBoxController::addNewItemBox() {
});
}
bool ProxiesBoxController::contains(const ProxyData &proxy) const {
const auto j = ranges::find(
_list,
proxy,
[](const Item &item) { return item.data; });
return (j != end(_list));
}
void ProxiesBoxController::addNewItem(const ProxyData &proxy) {
auto &proxies = _settings.list();
proxies.push_back(proxy);
+8 -1
View File
@@ -30,6 +30,10 @@ namespace Main {
class Account;
} // namespace Main
namespace Window {
class SessionController;
} // namespace Window
class ProxiesBoxController {
public:
using ProxyData = MTP::ProxyData;
@@ -38,6 +42,7 @@ public:
explicit ProxiesBoxController(not_null<Main::Account*> account);
static void ShowApplyConfirmation(
Window::SessionController *controller,
Type type,
const QMap<QString, QString> &fields);
@@ -77,6 +82,9 @@ public:
void setTryIPv6(bool enabled);
rpl::producer<ProxyData::Settings> proxySettingsValue() const;
[[nodiscard]] bool contains(const ProxyData &proxy) const;
void addNewItem(const ProxyData &proxy);
rpl::producer<ItemView> views() const;
~ProxiesBoxController();
@@ -109,7 +117,6 @@ private:
void replaceItemValue(
std::vector<Item>::iterator which,
const ProxyData &proxy);
void addNewItem(const ProxyData &proxy);
const not_null<Main::Account*> _account;
Core::SettingsProxy &_settings;
+256 -70
View File
@@ -7,33 +7,41 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/create_poll_box.h"
#include "lang/lang_keys.h"
#include "data/data_poll.h"
#include "ui/toast/toast.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/labels.h"
#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"
#include "base/call_delayed.h"
#include "base/event_filter.h"
#include "base/random.h"
#include "base/unique_qptr.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h"
#include "menu/menu_send.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "data/data_poll.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "history/view/history_view_schedule_box.h"
#include "base/unique_qptr.h"
#include "base/event_filter.h"
#include "base/call_delayed.h"
#include "base/random.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "menu/menu_send.h"
#include "ui/controls/emoji_button.h"
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h" // defaultComposeFiles.
#include "styles/style_layers.h"
#include "styles/style_settings.h"
namespace {
@@ -46,12 +54,107 @@ constexpr auto kSolutionLimit = 200;
constexpr auto kWarnSolutionLimit = 60;
constexpr auto kErrorLimit = 99;
[[nodiscard]] not_null<Ui::EmojiButton*> AddEmojiToggleToField(
not_null<Ui::InputField*> field,
not_null<Ui::BoxContent*> box,
not_null<Window::SessionController*> controller,
not_null<ChatHelpers::TabbedPanel*> emojiPanel,
QPoint shift) {
const auto emojiToggle = Ui::CreateChild<Ui::EmojiButton>(
field->parentWidget(),
st::defaultComposeFiles.emoji);
const auto fade = Ui::CreateChild<Ui::FadeAnimation>(
emojiToggle,
emojiToggle,
0.5);
{
const auto fadeTarget = Ui::CreateChild<Ui::RpWidget>(emojiToggle);
fadeTarget->resize(emojiToggle->size());
fadeTarget->paintRequest(
) | rpl::start_with_next([=](const QRect &rect) {
auto p = QPainter(fadeTarget);
if (fade->animating()) {
p.fillRect(fadeTarget->rect(), st::boxBg);
}
fade->paint(p);
}, fadeTarget->lifetime());
rpl::single(false) | rpl::then(
field->focusedChanges()
) | rpl::start_with_next([=](bool shown) {
if (shown) {
fade->fadeIn(st::universalDuration);
} else {
fade->fadeOut(st::universalDuration);
}
}, emojiToggle->lifetime());
fade->fadeOut(1);
fade->finish();
}
const auto outer = box->getDelegate()->outerContainer();
const auto allow = [](not_null<DocumentData*>) { return true; };
InitMessageFieldHandlers(
controller,
field,
Window::GifPauseReason::Layer,
allow);
Ui::Emoji::SuggestionsController::Init(
outer,
field,
&controller->session(),
Ui::Emoji::SuggestionsController::Options{
.suggestCustomEmoji = true,
.allowCustomWithoutPremium = allow,
});
const auto updateEmojiPanelGeometry = [=] {
const auto parent = emojiPanel->parentWidget();
const auto global = emojiToggle->mapToGlobal({ 0, 0 });
const auto local = parent->mapFromGlobal(global);
const auto right = local.x() + emojiToggle->width() * 3;
const auto isDropDown = local.y() < parent->height() / 2;
emojiPanel->setDropDown(isDropDown);
if (isDropDown) {
emojiPanel->moveTopRight(
local.y() + emojiToggle->height(),
right);
} else {
emojiPanel->moveBottomRight(local.y(), right);
}
};
rpl::combine(
box->sizeValue(),
field->geometryValue()
) | rpl::start_with_next([=](QSize outer, QRect inner) {
emojiToggle->moveToLeft(
rect::right(inner) + shift.x(),
inner.y() + shift.y());
emojiToggle->update();
}, emojiToggle->lifetime());
emojiToggle->installEventFilter(emojiPanel);
emojiToggle->addClickHandler([=] {
updateEmojiPanelGeometry();
emojiPanel->toggleAnimated();
});
const auto filterCallback = [=](not_null<QEvent*> event) {
if (event->type() == QEvent::Enter) {
updateEmojiPanelGeometry();
}
return base::EventFilterResult::Continue;
};
base::install_event_filter(emojiToggle, filterCallback);
return emojiToggle;
}
class Options {
public:
Options(
not_null<QWidget*> outer,
not_null<Ui::BoxContent*> box,
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session,
not_null<Window::SessionController*> controller,
ChatHelpers::TabbedPanel *emojiPanel,
bool chooseCorrectEnabled);
[[nodiscard]] bool hasOptions() const;
@@ -140,9 +243,10 @@ private:
[[nodiscard]] auto createChooseCorrectGroup()
-> std::shared_ptr<Ui::RadiobuttonGroup>;
not_null<QWidget*> _outer;
not_null<Ui::BoxContent*> _box;
not_null<Ui::VerticalLayout*> _container;
const not_null<Main::Session*> _session;
const not_null<Window::SessionController*> _controller;
ChatHelpers::TabbedPanel * const _emojiPanel;
std::shared_ptr<Ui::RadiobuttonGroup> _chooseCorrectGroup;
int _position = 0;
std::vector<std::unique_ptr<Option>> _list;
@@ -154,6 +258,7 @@ private:
rpl::event_stream<not_null<QWidget*>> _scrollToWidget;
rpl::event_stream<> _backspaceInFront;
rpl::event_stream<> _tabbed;
rpl::lifetime _emojiPanelLifetime;
};
@@ -193,8 +298,9 @@ not_null<Ui::FlatLabel*> CreateWarningLabel(
if (value >= 0) {
result->setText(QString::number(value));
} else {
constexpr auto kMinus = QChar(0x2212);
result->setMarkedText(Ui::Text::Colorized(
QString::number(value)));
kMinus + QString::number(std::abs(value))));
}
result->setVisible(shown);
}));
@@ -223,7 +329,9 @@ Options::Option::Option(
, _field(
Ui::CreateChild<Ui::InputField>(
_content.get(),
st::createPollOptionField,
session->user()->isPremium()
? st::createPollOptionFieldPremium
: st::createPollOptionField,
Ui::InputField::Mode::NoNewlines,
tr::lng_polls_create_option_add())) {
InitField(outer, _field, session);
@@ -299,7 +407,7 @@ void Options::Option::createRemove() {
const auto remove = Ui::CreateChild<Ui::CrossButton>(
field.get(),
st::createPollOptionRemove);
remove->hide(anim::type::instant);
remove->show(anim::type::instant);
const auto toggle = lifetime.make_state<rpl::variable<bool>>(false);
_removeAlways = lifetime.make_state<rpl::variable<bool>>(false);
@@ -309,6 +417,7 @@ void Options::Option::createRemove() {
// Don't capture 'this'! Because Option is a value type.
*toggle = !field->getLastText().isEmpty();
}, field->lifetime());
#if 0
rpl::combine(
toggle->value(),
_removeAlways->value(),
@@ -316,6 +425,7 @@ void Options::Option::createRemove() {
) | rpl::start_with_next([=](bool shown) {
remove->toggle(shown, anim::type::normal);
}, remove->lifetime());
#endif
field->widthValue(
) | rpl::start_with_next([=](int width) {
@@ -456,10 +566,16 @@ void Options::Option::removePlaceholder() const {
PollAnswer Options::Option::toPollAnswer(int index) const {
Expects(index >= 0 && index < kMaxOptionsCount);
const auto text = field()->getTextWithTags();
auto result = PollAnswer{
field()->getLastText().trimmed(),
QByteArray(1, ('0' + index))
TextWithEntities{
.text = text.text,
.entities = TextUtilities::ConvertTextTagsToEntities(text.tags),
},
QByteArray(1, ('0' + index)),
};
TextUtilities::Trim(result.text);
result.correct = _correct ? _correct->entity()->Checkbox::checked() : false;
return result;
}
@@ -469,13 +585,15 @@ rpl::producer<Qt::MouseButton> Options::Option::removeClicks() const {
}
Options::Options(
not_null<QWidget*> outer,
not_null<Ui::BoxContent*> box,
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session,
not_null<Window::SessionController*> controller,
ChatHelpers::TabbedPanel *emojiPanel,
bool chooseCorrectEnabled)
: _outer(outer)
: _box(box)
, _container(container)
, _session(session)
, _controller(controller)
, _emojiPanel(emojiPanel)
, _chooseCorrectGroup(chooseCorrectEnabled
? createChooseCorrectGroup()
: nullptr)
@@ -645,12 +763,40 @@ void Options::addEmptyOption() {
(*(_list.end() - 2))->toggleRemoveAlways(true);
}
_list.push_back(std::make_unique<Option>(
_outer,
_box,
_container,
_session,
&_controller->session(),
_position + _list.size() + _destroyed.size(),
_chooseCorrectGroup));
const auto field = _list.back()->field();
if (const auto emojiPanel = _emojiPanel) {
const auto emojiToggle = AddEmojiToggleToField(
field,
_box,
_controller,
emojiPanel,
QPoint(
-st::createPollOptionFieldPremium.textMargins.right(),
st::createPollOptionEmojiPositionSkip));
emojiToggle->shownValue() | rpl::start_with_next([=](bool shown) {
if (!shown) {
return;
}
_emojiPanelLifetime.destroy();
emojiPanel->selector()->emojiChosen(
) | rpl::start_with_next([=](ChatHelpers::EmojiChosen data) {
if (field->hasFocus()) {
Ui::InsertEmojiAtCursor(field->textCursor(), data.emoji);
}
}, _emojiPanelLifetime);
emojiPanel->selector()->customEmojiChosen(
) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
if (field->hasFocus()) {
Data::InsertCustomEmoji(field, data.document);
}
}, _emojiPanelLifetime);
}, emojiToggle->lifetime());
}
field->submits(
) | rpl::start_with_next([=] {
const auto index = findField(field);
@@ -697,7 +843,7 @@ void Options::addEmptyOption() {
});
_list.back()->removeClicks(
) | rpl::take(1) | rpl::start_with_next([=] {
) | rpl::start_with_next([=] {
Ui::PostponeCall(crl::guard(field, [=] {
Expects(!_list.empty());
@@ -764,12 +910,12 @@ CreatePollBox::CreatePollBox(
PollData::Flags chosen,
PollData::Flags disabled,
Api::SendType sendType,
SendMenu::Type sendMenuType)
SendMenu::Details sendMenuDetails)
: _controller(controller)
, _chosen(chosen)
, _disabled(disabled)
, _sendType(sendType)
, _sendMenuType(sendMenuType) {
, _sendMenuDetails([result = sendMenuDetails] { return result; }) {
}
rpl::producer<CreatePollBox::Result> CreatePollBox::submitRequests() const {
@@ -789,19 +935,63 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
using namespace Settings;
const auto session = &_controller->session();
const auto isPremium = session->user()->isPremium();
Ui::AddSubsectionTitle(container, tr::lng_polls_create_question());
const auto question = container->add(
object_ptr<Ui::InputField>(
container,
st::createPollField,
Ui::InputField::Mode::MultiLine,
tr::lng_polls_create_question_placeholder()),
st::createPollFieldPadding);
st::createPollFieldPadding
+ (isPremium
? QMargins(0, 0, st::defaultComposeFiles.emoji.inner.width, 0)
: QMargins()));
InitField(getDelegate()->outerContainer(), question, session);
question->setMaxLength(kQuestionLimit + kErrorLimit);
question->setSubmitSettings(Ui::InputField::SubmitSettings::Both);
question->customTab(true);
if (isPremium) {
using Selector = ChatHelpers::TabbedSelector;
const auto outer = getDelegate()->outerContainer();
_emojiPanel = base::make_unique_q<ChatHelpers::TabbedPanel>(
outer,
_controller,
object_ptr<Selector>(
nullptr,
_controller->uiShow(),
Window::GifPauseReason::Layer,
Selector::Mode::EmojiOnly));
const auto emojiPanel = _emojiPanel.get();
emojiPanel->setDesiredHeightValues(
1.,
st::emojiPanMinHeight / 2,
st::emojiPanMinHeight);
emojiPanel->hide();
emojiPanel->selector()->setCurrentPeer(session->user());
const auto emojiToggle = AddEmojiToggleToField(
question,
this,
_controller,
emojiPanel,
st::createPollOptionFieldPremiumEmojiPosition);
emojiPanel->selector()->emojiChosen(
) | rpl::start_with_next([=](ChatHelpers::EmojiChosen data) {
if (question->hasFocus()) {
Ui::InsertEmojiAtCursor(question->textCursor(), data.emoji);
}
}, emojiToggle->lifetime());
emojiPanel->selector()->customEmojiChosen(
) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
if (question->hasFocus()) {
Data::InsertCustomEmoji(question, data.document);
}
}, emojiToggle->lifetime());
}
const auto warning = CreateWarningLabel(
container,
question,
@@ -854,7 +1044,7 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
solution->setInstantReplaces(Ui::InstantReplaces::Default());
solution->setInstantReplacesEnabled(
Core::App().settings().replaceEmojiValue());
solution->setMarkdownReplacesEnabled(rpl::single(true));
solution->setMarkdownReplacesEnabled(true);
solution->setEditLinkCallback(
DefaultEditLinkCallback(_controller->uiShow(), solution));
solution->customTab(true);
@@ -910,9 +1100,10 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
st::defaultSubsectionTitle),
st::createPollFieldTitlePadding);
const auto options = lifetime().make_state<Options>(
getDelegate()->outerContainer(),
this,
container,
&_controller->session(),
_controller,
_emojiPanel ? _emojiPanel.get() : nullptr,
(_chosen & PollData::Flag::Quiz));
auto limit = options->usedCount() | rpl::after_next([=](int count) {
setCloseByEscape(!count);
@@ -1029,9 +1220,13 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
};
const auto collectResult = [=] {
const auto textWithTags = question->getTextWithTags();
using Flag = PollData::Flag;
auto result = PollData(&_controller->session().data(), id);
result.question = question->getLastText().trimmed();
result.question.text = textWithTags.text;
result.question.entities = TextUtilities::ConvertTextTagsToEntities(
textWithTags.tags);
TextUtilities::Trim(result.question);
result.answers = options->toPollAnswers();
const auto solutionWithTags = quiz->checked()
? solution->getTextWithAppliedMarkdown()
@@ -1093,19 +1288,9 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
_submitRequests.fire({ collectResult(), sendOptions });
}
};
const auto sendSilent = [=] {
send({ .silent = true });
};
const auto sendScheduled = [=] {
_controller->show(
HistoryView::PrepareScheduleBox(
this,
SendMenu::Type::Scheduled,
send));
};
const auto sendWhenOnline = [=] {
send(Api::DefaultSendWhenOnlineOptions());
};
const auto sendAction = SendMenu::DefaultCallback(
_controller->uiShow(),
crl::guard(this, send));
options->scrollToWidget(
) | rpl::start_with_next([=](not_null<QWidget*> widget) {
@@ -1118,24 +1303,25 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
}, lifetime());
const auto isNormal = (_sendType == Api::SendType::Normal);
const auto schedule = [=] {
sendAction(
{ .type = SendMenu::ActionType::Schedule },
_sendMenuDetails());
};
const auto submit = addButton(
isNormal
(isNormal
? tr::lng_polls_create_button()
: tr::lng_schedule_button(),
[=] { isNormal ? send({}) : sendScheduled(); });
const auto sendMenuType = [=] {
: tr::lng_schedule_button()),
[=] { isNormal ? send({}) : schedule(); });
const auto sendMenuDetails = [=] {
collectError();
return (*error)
? SendMenu::Type::Disabled
: _sendMenuType;
return (*error) ? SendMenu::Details() : _sendMenuDetails();
};
SendMenu::SetupMenuAndShortcuts(
submit.data(),
sendMenuType,
sendSilent,
sendScheduled,
sendWhenOnline);
_controller->uiShow(),
sendMenuDetails,
sendAction);
addButton(tr::lng_cancel(), [=] { closeBox(); });
return result;
+8 -3
View File
@@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
struct PollData;
namespace ChatHelpers {
class TabbedPanel;
} // namespace ChatHelpers
namespace Ui {
class VerticalLayout;
} // namespace Ui
@@ -23,7 +27,7 @@ class SessionController;
} // namespace Window
namespace SendMenu {
enum class Type;
struct Details;
} // namespace SendMenu
class CreatePollBox : public Ui::BoxContent {
@@ -39,7 +43,7 @@ public:
PollData::Flags chosen,
PollData::Flags disabled,
Api::SendType sendType,
SendMenu::Type sendMenuType);
SendMenu::Details sendMenuDetails);
[[nodiscard]] rpl::producer<Result> submitRequests() const;
void submitFailed(const QString &error);
@@ -71,7 +75,8 @@ private:
const PollData::Flags _chosen = PollData::Flags();
const PollData::Flags _disabled = PollData::Flags();
const Api::SendType _sendType = Api::SendType();
const SendMenu::Type _sendMenuType;
const Fn<SendMenu::Details()> _sendMenuDetails;
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
Fn<void()> _setInnerFocus;
Fn<rpl::producer<bool>()> _dataIsValidValue;
rpl::event_stream<Result> _submitRequests;
@@ -232,8 +232,8 @@ void DeleteMessagesBox::prepare() {
if (hasScheduledMessages()) {
} else if (auto revoke = revokeText(peer)) {
const auto &settings = Core::App().settings();
const auto revokeByDefault =
!settings.rememberedDeleteMessageOnlyForYou();
const auto revokeByDefault
= !settings.rememberedDeleteMessageOnlyForYou();
_revoke.create(
this,
revoke->checkbox,
@@ -379,13 +379,7 @@ auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
return result;
}
const auto items = ranges::views::all(
_ids
) | ranges::views::transform([&](FullMsgId id) {
return peer->owner().message(id);
}) | ranges::views::filter([](HistoryItem *item) {
return (item != nullptr);
}) | ranges::to_vector;
const auto items = peer->owner().idsToItems(_ids);
if (items.size() != _ids.size()) {
// We don't have information about all messages.
+67 -23
View File
@@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "mainwidget.h" // controller->content() -> QWidget*
#include "menu/menu_send.h"
#include "mtproto/mtproto_config.h"
#include "platform/platform_specific.h"
#include "storage/localimageloader.h" // SendMediaType
@@ -175,7 +176,7 @@ void ChooseReplacement(
void EditPhotoImage(
not_null<Window::SessionController*> controller,
std::shared_ptr<Data::PhotoMedia> media,
bool wasSpoiler,
bool spoilered,
Fn<void(Ui::PreparedList)> done) {
const auto large = media
? media->image(Data::PhotoSize::Large)
@@ -198,7 +199,7 @@ void EditPhotoImage(
using ImageInfo = Ui::PreparedFileInformation::Image;
auto &file = list.files.front();
file.spoiler = wasSpoiler;
file.spoiler = spoilered;
const auto image = std::get_if<ImageInfo>(&file.information->media);
image->modifications = mods;
@@ -206,6 +207,9 @@ void EditPhotoImage(
Storage::UpdateImageDetails(file, previewWidth, sideLimit);
done(std::move(list));
};
if (!large) {
return;
}
const auto fileImage = std::make_shared<Image>(*large);
auto editor = base::make_unique_q<Editor::PhotoEditor>(
parent,
@@ -222,25 +226,18 @@ void EditPhotoImage(
} // namespace
EditCaptionBox::EditCaptionBox(
QWidget*,
not_null<Window::SessionController*> controller,
not_null<HistoryItem*> item)
: EditCaptionBox({}, controller, item, PrepareEditText(item), {}, {}) {
}
EditCaptionBox::EditCaptionBox(
QWidget*,
not_null<Window::SessionController*> controller,
not_null<HistoryItem*> item,
TextWithTags &&text,
bool spoilered,
bool invertCaption,
Ui::PreparedList &&list,
Fn<void()> saved)
: _controller(controller)
, _historyItem(item)
, _isAllowedEditMedia(item->media()
? item->media()->allowsEditMedia()
: false)
, _isAllowedEditMedia(item->media() && item->media()->allowsEditMedia())
, _albumType(ComputeAlbumType(item))
, _controls(base::make_unique_q<Ui::VerticalLayout>(this))
, _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
@@ -258,6 +255,8 @@ EditCaptionBox::EditCaptionBox(
Expects(item->media() != nullptr);
Expects(item->media()->allowsEditCaption());
_mediaEditManager.start(item, spoilered, invertCaption);
_controller->session().data().itemRemoved(
_historyItem->fullId()
) | rpl::start_with_next([=] {
@@ -271,6 +270,8 @@ void EditCaptionBox::StartMediaReplace(
not_null<Window::SessionController*> controller,
FullMsgId itemId,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved) {
const auto session = &controller->session();
const auto item = session->data().message(itemId);
@@ -282,6 +283,8 @@ void EditCaptionBox::StartMediaReplace(
controller,
item,
std::move(text),
spoilered,
invertCaption,
std::move(list),
std::move(saved)));
};
@@ -296,6 +299,8 @@ void EditCaptionBox::StartMediaReplace(
FullMsgId itemId,
Ui::PreparedList &&list,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved) {
const auto session = &controller->session();
const auto item = session->data().message(itemId);
@@ -329,6 +334,8 @@ void EditCaptionBox::StartMediaReplace(
controller,
item,
std::move(text),
spoilered,
invertCaption,
std::move(list),
std::move(saved)));
}
@@ -339,14 +346,15 @@ void EditCaptionBox::StartPhotoEdit(
std::shared_ptr<Data::PhotoMedia> media,
FullMsgId itemId,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved) {
const auto session = &controller->session();
const auto item = session->data().message(itemId);
if (!item) {
return;
}
const auto hasSpoiler = item->media() && item->media()->hasSpoiler();
EditPhotoImage(controller, media, hasSpoiler, [=](
EditPhotoImage(controller, media, spoilered, [=](
Ui::PreparedList &&list) mutable {
const auto item = session->data().message(itemId);
if (!item) {
@@ -356,15 +364,48 @@ void EditCaptionBox::StartPhotoEdit(
controller,
item,
std::move(text),
spoilered,
invertCaption,
std::move(list),
std::move(saved)));
});
}
void EditCaptionBox::prepare() {
addButton(tr::lng_settings_save(), [=] { save(); });
const auto button = addButton(tr::lng_settings_save(), [=] { save(); });
addButton(tr::lng_cancel(), [=] { closeBox(); });
const auto details = crl::guard(this, [=] {
auto result = SendMenu::Details();
const auto allWithSpoilers = ranges::all_of(
_preparedList.files,
&Ui::PreparedFile::spoiler);
result.spoiler = !_preparedList.hasSpoilerMenu(!_asFile)
? SendMenu::SpoilerState::None
: allWithSpoilers
? SendMenu::SpoilerState::Enabled
: SendMenu::SpoilerState::Possible;
const auto canMoveCaption = _preparedList.canMoveCaption(
false,
!_asFile
) && _field && HasSendText(_field);
result.caption = !canMoveCaption
? SendMenu::CaptionState::None
: _mediaEditManager.invertCaption()
? SendMenu::CaptionState::Above
: SendMenu::CaptionState::Below;
return result;
});
const auto callback = [=](SendMenu::Action action, const auto &) {
_mediaEditManager.apply(action);
rebuildPreview();
};
SendMenu::SetupMenuAndShortcuts(
button,
nullptr,
details,
crl::guard(this, callback));
updateBoxSize();
setupField();
@@ -393,7 +434,6 @@ void EditCaptionBox::rebuildPreview() {
applyChanges();
_previewHasSpoiler = nullptr;
if (_preparedList.files.empty()) {
const auto media = _historyItem->media();
const auto photo = media->photo();
@@ -427,7 +467,13 @@ void EditCaptionBox::rebuildPreview() {
_isPhoto = (media && media->isPhoto());
const auto withCheckbox = _isPhoto && CanBeCompressed(_albumType);
if (media && (!withCheckbox || !_asFile)) {
_previewHasSpoiler = [media] { return media->hasSpoiler(); };
media->spoileredChanges(
) | rpl::start_with_next([=](bool spoilered) {
_mediaEditManager.apply({ .type = spoilered
? SendMenu::ActionType::SpoilerOn
: SendMenu::ActionType::SpoilerOff
});
}, media->lifetime());
_content.reset(media);
} else {
_content.reset(Ui::CreateChild<Ui::SingleFilePreview>(
@@ -754,10 +800,7 @@ bool EditCaptionBox::setPreparedList(Ui::PreparedList &&list) {
}
bool EditCaptionBox::hasSpoiler() const {
return _preparedList.files.empty()
? (_historyItem->media()
&& _historyItem->media()->hasSpoiler())
: _preparedList.files.front().spoiler;
return _mediaEditManager.spoilered();
}
void EditCaptionBox::captionResized() {
@@ -866,8 +909,8 @@ bool EditCaptionBox::validateLength(const QString &text) const {
}
void EditCaptionBox::applyChanges() {
if (!_preparedList.files.empty() && _previewHasSpoiler) {
_preparedList.files.front().spoiler = _previewHasSpoiler();
if (!_preparedList.files.empty()) {
_preparedList.files.front().spoiler = _mediaEditManager.spoilered();
}
}
@@ -896,6 +939,7 @@ void EditCaptionBox::save() {
auto options = Api::SendOptions();
options.scheduled = item->isScheduled() ? item->date() : 0;
options.shortcutId = item->shortcutId();
options.invertCaption = _mediaEditManager.invertCaption();
if (!_preparedList.files.empty()) {
if ((_albumType != Ui::AlbumType::None)
+10 -5
View File
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "history/view/controls/history_view_compose_media_edit_manager.h"
#include "ui/layers/box_content.h"
#include "ui/chat/attach/attach_prepare.h"
@@ -32,15 +33,13 @@ enum class AlbumType;
class EditCaptionBox final : public Ui::BoxContent {
public:
EditCaptionBox(
QWidget*,
not_null<Window::SessionController*> controller,
not_null<HistoryItem*> item);
EditCaptionBox(
QWidget*,
not_null<Window::SessionController*> controller,
not_null<HistoryItem*> item,
TextWithTags &&text,
bool spoilered,
bool invertCaption,
Ui::PreparedList &&list,
Fn<void()> saved);
~EditCaptionBox();
@@ -49,18 +48,24 @@ public:
not_null<Window::SessionController*> controller,
FullMsgId itemId,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved);
static void StartMediaReplace(
not_null<Window::SessionController*> controller,
FullMsgId itemId,
Ui::PreparedList &&list,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved);
static void StartPhotoEdit(
not_null<Window::SessionController*> controller,
std::shared_ptr<Data::PhotoMedia> media,
FullMsgId itemId,
TextWithTags text,
bool spoilered,
bool invertCaption,
Fn<void()> saved);
protected:
@@ -111,7 +116,6 @@ private:
const base::unique_qptr<Ui::EmojiButton> _emojiToggle;
base::unique_qptr<Ui::AbstractSinglePreview> _content;
Fn<bool()> _previewHasSpoiler;
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
base::unique_qptr<QObject> _emojiFilter;
@@ -122,6 +126,7 @@ private:
std::shared_ptr<Data::PhotoMedia> _photoMedia;
Ui::PreparedList _preparedList;
HistoryView::MediaEditManager _mediaEditManager;
mtpRequestId _saveRequestId = 0;
@@ -159,10 +159,7 @@ public:
-> rpl::producer<RowSelectionChange>;
private:
[[nodiscard]] std::unique_ptr<PeerListRow> createRow() const;
const not_null<Main::Session*> _session;
bool _premiums = false;
rpl::event_stream<> _selectionChanged;
rpl::event_stream<RowSelectionChange> _rowSelectionChanges;
@@ -209,8 +206,7 @@ bool PremiumsRow::useForumLikeUserpic() const {
TypesController::TypesController(
not_null<Main::Session*> session,
bool premiums)
: _session(session)
, _premiums(premiums) {
: _session(session) {
}
Main::Session &TypesController::session() const {
@@ -331,6 +327,9 @@ auto PrivacyExceptionsBoxController::preparePremiumsRowList()
_deselectOption = [=](PeerListRowId itemId) {
if (const auto row = _typesDelegate->peerListFindRow(itemId)) {
if (itemId == kPremiumsRowId) {
_selected.premiums = false;
}
_typesDelegate->peerListSetRowChecked(row, false);
}
};
+89 -40
View File
@@ -16,10 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#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_credits.h"
#include "data/data_media_types.h" // Data::GiveawayStart.
#include "data/data_peer_values.h" // Data::PeerPremiumValue.
#include "data/data_session.h"
@@ -48,6 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/gradient_round_button.h"
#include "ui/widgets/label_with_custom_emoji.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/table_layout.h"
@@ -319,21 +320,20 @@ void GiftBox(
std::move(titleLabel)),
st::premiumGiftTitlePadding);
auto textLabel = object_ptr<Ui::FlatLabel>(box, st::premiumPreviewAbout);
tr::lng_premium_gift_about(
lt_user,
user->session().changes().peerFlagsValue(
user,
Data::PeerUpdate::Flag::Name
) | rpl::map([=] { return TextWithEntities{ user->firstName }; }),
Ui::Text::RichLangValue
) | rpl::map(
BoostsForGiftText({ user })
) | rpl::start_with_next([
raw = textLabel.data(),
session = &user->session()](const TextWithEntities &t) {
raw->setMarkedText(t, Core::MarkedTextContext{ .session = session });
}, textLabel->lifetime());
auto textLabel = Ui::CreateLabelWithCustomEmoji(
box,
tr::lng_premium_gift_about(
lt_user,
user->session().changes().peerFlagsValue(
user,
Data::PeerUpdate::Flag::Name
) | rpl::map([=] { return TextWithEntities{ user->firstName }; }),
Ui::Text::RichLangValue
) | rpl::map(
BoostsForGiftText({ user })
),
{ .session = &user->session() },
st::premiumPreviewAbout);
textLabel->setTextColorOverride(stTitle.textFg->c);
textLabel->resizeToWidth(available);
box->addRow(
@@ -536,14 +536,12 @@ void GiftsBox(
const auto label = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,
object_ptr<Ui::FlatLabel>(box, st::premiumPreviewAbout)),
Ui::CreateLabelWithCustomEmoji(
box,
std::move(text),
{ .session = session },
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);
}
@@ -1150,16 +1148,18 @@ void GiftCodeBox(
object_ptr<Ui::Premium::TopBar>(
box,
st::giveawayGiftCodeCover,
nullptr,
rpl::conditional(
state->used.value(),
tr::lng_gift_link_used_title(),
tr::lng_gift_link_title()),
rpl::conditional(
state->used.value(),
tr::lng_gift_link_used_about(Ui::Text::RichLangValue),
tr::lng_gift_link_about(Ui::Text::RichLangValue)),
true));
Ui::Premium::TopBarDescriptor{
.clickContextOther = nullptr,
.title = rpl::conditional(
state->used.value(),
tr::lng_gift_link_used_title(),
tr::lng_gift_link_title()),
.about = rpl::conditional(
state->used.value(),
tr::lng_gift_link_used_about(Ui::Text::RichLangValue),
tr::lng_gift_link_about(Ui::Text::RichLangValue)),
.light = true,
}));
const auto max = st::giveawayGiftCodeTopHeight;
bar->setMaximumHeight(max);
@@ -1286,13 +1286,15 @@ void GiftCodePendingBox(
object_ptr<Ui::Premium::TopBar>(
box,
st,
clickContext,
tr::lng_gift_link_title(),
tr::lng_gift_link_pending_about(
lt_user,
rpl::single(Ui::Text::Link(resultToName)),
Ui::Text::RichLangValue),
true));
Ui::Premium::TopBarDescriptor{
.clickContextOther = clickContext,
.title = tr::lng_gift_link_title(),
.about = tr::lng_gift_link_pending_about(
lt_user,
rpl::single(Ui::Text::Link(resultToName)),
Ui::Text::RichLangValue),
.light = true,
}));
const auto max = st::giveawayGiftCodeTopHeight;
bar->setMaximumHeight(max);
@@ -1632,3 +1634,50 @@ void ResolveGiveawayInfo(
messageId,
crl::guard(controller, show));
}
void AddCreditsHistoryEntryTable(
not_null<Window::SessionNavigation*> controller,
not_null<Ui::VerticalLayout*> container,
const Data::CreditsHistoryEntry &entry) {
auto table = container->add(
object_ptr<Ui::TableLayout>(
container,
st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
if (entry.bareId) {
AddTableRow(
table,
tr::lng_credits_box_history_entry_peer(),
controller,
PeerId(entry.bareId));
}
if (!entry.id.isEmpty()) {
constexpr auto kOneLineCount = 18;
const auto oneLine = entry.id.length() <= kOneLineCount;
auto label = object_ptr<Ui::FlatLabel>(
table,
rpl::single(
Ui::Text::Wrapped({ entry.id }, EntityType::Code, {})),
oneLine
? st::giveawayGiftCodeValue
: st::giveawayGiftCodeValueMultiline);
label->setClickHandlerFilter([=](const auto &...) {
TextUtilities::SetClipboardText(
TextForMimeData::Simple(entry.id));
controller->showToast(
tr::lng_credits_box_history_entry_id_copied(tr::now));
return false;
});
AddTableRow(
table,
tr::lng_credits_box_history_entry_id(),
std::move(label),
st::giveawayGiftCodeValueMargin);
}
if (!entry.date.isNull()) {
AddTableRow(
table,
tr::lng_gift_link_label_date(),
rpl::single(Ui::Text::WithEntities(langDateTime(entry.date))));
}
}
@@ -16,12 +16,14 @@ struct GiftCode;
} // namespace Api
namespace Data {
struct CreditsHistoryEntry;
struct GiveawayStart;
struct GiveawayResults;
} // namespace Data
namespace Ui {
class GenericBox;
class VerticalLayout;
} // namespace Ui
namespace Window {
@@ -71,3 +73,8 @@ void ResolveGiveawayInfo(
MsgId messageId,
std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results);
void AddCreditsHistoryEntryTable(
not_null<Window::SessionNavigation*> controller,
not_null<Ui::VerticalLayout*> container,
const Data::CreditsHistoryEntry &entry);
@@ -0,0 +1,856 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/moderate_messages_box.h"
#include "api/api_chat_participants.h"
#include "api/api_messages_search.h"
#include "apiwrap.h"
#include "base/event_filter.h"
#include "base/timer.h"
#include "boxes/delete_messages_box.h"
#include "boxes/peers/edit_peer_permissions_box.h"
#include "core/application.h"
#include "core/ui_integration.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_chat_participant_status.h"
#include "data/data_histories.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "history/history.h"
#include "history/history_item.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "ui/boxes/confirm_box.h"
#include "ui/controls/userpic_button.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/toggle_arrow.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/rect_part.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "ui/widgets/checkbox.h"
#include "ui/wrap/slide_wrap.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_window.h"
namespace {
using Participants = std::vector<not_null<PeerData*>>;
struct ModerateOptions final {
bool allCanBan = false;
bool allCanDelete = false;
Participants participants;
};
ModerateOptions CalculateModerateOptions(const HistoryItemsList &items) {
Expects(!items.empty());
auto result = ModerateOptions{
.allCanBan = true,
.allCanDelete = true,
};
const auto peer = items.front()->history()->peer;
for (const auto &item : items) {
if (!result.allCanBan && !result.allCanDelete) {
return {};
}
if (peer != item->history()->peer) {
return {};
}
if (!item->suggestBanReport()) {
result.allCanBan = false;
}
if (!item->suggestDeleteAllReport()) {
result.allCanDelete = false;
}
if (const auto p = item->from()) {
if (!ranges::contains(result.participants, not_null{ p })) {
result.participants.push_back(p);
}
}
}
return result;
}
[[nodiscard]] rpl::producer<int> MessagesCountValue(
not_null<History*> history,
not_null<PeerData*> from) {
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
auto search = lifetime.make_state<Api::MessagesSearch>(history);
consumer.put_next(0);
search->messagesFounds(
) | rpl::start_with_next([=](const Api::FoundMessages &found) {
consumer.put_next_copy(found.total);
}, lifetime);
search->searchMessages({ .from = from });
return lifetime;
};
}
class Button final : public Ui::RippleButton {
public:
Button(not_null<QWidget*> parent, int count);
void setChecked(bool checked);
[[nodiscard]] bool checked() const;
[[nodiscard]] static QSize ComputeSize(int);
private:
void paintEvent(QPaintEvent *event) override;
QImage prepareRippleMask() const override;
QPoint prepareRippleStartPosition() const override;
const int _count;
const QString _text;
bool _checked = false;
Ui::Animations::Simple _animation;
};
Button::Button(not_null<QWidget*> parent, int count)
: RippleButton(parent, st::defaultRippleAnimation)
, _count(count)
, _text(QString::number(std::abs(_count))) {
}
QSize Button::ComputeSize(int count) {
return QSize(
st::moderateBoxExpandHeight
+ st::moderateBoxExpand.width()
+ st::moderateBoxExpandInnerSkip * 4
+ st::moderateBoxExpandFont->width(
QString::number(std::abs(count)))
+ st::moderateBoxExpandToggleSize,
st::moderateBoxExpandHeight);
}
void Button::setChecked(bool checked) {
if (_checked == checked) {
return;
}
_checked = checked;
_animation.stop();
_animation.start(
[=] { update(); },
checked ? 0 : 1,
checked ? 1 : 0,
st::slideWrapDuration);
}
bool Button::checked() const {
return _checked;
}
void Button::paintEvent(QPaintEvent *event) {
auto p = Painter(this);
auto hq = PainterHighQualityEnabler(p);
Ui::RippleButton::paintRipple(p, QPoint());
const auto radius = height() / 2;
p.setPen(Qt::NoPen);
st::moderateBoxExpand.paint(
p,
radius,
(height() - st::moderateBoxExpand.height()) / 2,
width());
const auto innerSkip = st::moderateBoxExpandInnerSkip;
p.setBrush(Qt::NoBrush);
p.setPen(st::boxTextFg);
p.setFont(st::moderateBoxExpandFont);
p.drawText(
QRect(
innerSkip + radius + st::moderateBoxExpand.width(),
0,
width(),
height()),
_text,
style::al_left);
const auto path = Ui::ToggleUpDownArrowPath(
width() - st::moderateBoxExpandToggleSize - radius,
height() / 2,
st::moderateBoxExpandToggleSize,
st::moderateBoxExpandToggleFourStrokes,
_animation.value(_checked ? 1. : 0.));
p.fillPath(path, st::boxTextFg);
}
QImage Button::prepareRippleMask() const {
return Ui::RippleAnimation::RoundRectMask(size(), size().height() / 2);
}
QPoint Button::prepareRippleStartPosition() const {
return mapFromGlobal(QCursor::pos());
}
} // namespace
void CreateModerateMessagesBox(
not_null<Ui::GenericBox*> box,
const HistoryItemsList &items,
Fn<void()> confirmed) {
struct Controller final {
rpl::event_stream<bool> toggleRequestsFromTop;
rpl::event_stream<bool> toggleRequestsFromInner;
rpl::event_stream<bool> checkAllRequests;
Fn<Participants()> collectRequests;
};
const auto [allCanBan, allCanDelete, participants]
= CalculateModerateOptions(items);
const auto inner = box->verticalLayout();
Assert(!participants.empty());
const auto confirms = inner->lifetime().make_state<rpl::event_stream<>>();
const auto isSingle = participants.size() == 1;
const auto buttonPadding = isSingle
? QMargins()
: QMargins(0, 0, Button::ComputeSize(participants.size()).width(), 0);
const auto session = &items.front()->history()->session();
const auto historyPeerId = items.front()->history()->peer->id;
using Request = Fn<void(not_null<PeerData*>, not_null<ChannelData*>)>;
const auto sequentiallyRequest = [=](
Request request,
Participants participants) {
constexpr auto kSmallDelayMs = 5;
const auto participantIds = ranges::views::all(
participants
) | ranges::views::transform([](not_null<PeerData*> peer) {
return peer->id;
}) | ranges::to_vector;
const auto lifetime = std::make_shared<rpl::lifetime>();
const auto counter = lifetime->make_state<int>(0);
const auto timer = lifetime->make_state<base::Timer>();
timer->setCallback(crl::guard(session, [=] {
if ((*counter) < participantIds.size()) {
const auto peer = session->data().peer(historyPeerId);
const auto channel = peer ? peer->asChannel() : nullptr;
const auto from = session->data().peer(
participantIds[*counter]);
if (channel && from) {
request(from, channel);
}
(*counter)++;
} else {
lifetime->destroy();
}
}));
timer->callEach(kSmallDelayMs);
};
const auto handleConfirmation = [=](
not_null<Ui::Checkbox*> checkbox,
not_null<Controller*> controller,
Request request) {
confirms->events() | rpl::start_with_next([=] {
if (checkbox->checked() && controller->collectRequests) {
sequentiallyRequest(request, controller->collectRequests());
}
}, checkbox->lifetime());
};
const auto isEnter = [=](not_null<QEvent*> event) {
if (event->type() == QEvent::KeyPress) {
if (const auto k = static_cast<QKeyEvent*>(event.get())) {
return (k->key() == Qt::Key_Enter)
|| (k->key() == Qt::Key_Return);
}
}
return false;
};
base::install_event_filter(box, [=](not_null<QEvent*> event) {
if (isEnter(event)) {
box->triggerButton(0);
return base::EventFilterResult::Cancel;
}
return base::EventFilterResult::Continue;
});
const auto handleSubmition = [=](not_null<Ui::Checkbox*> checkbox) {
base::install_event_filter(box, [=](not_null<QEvent*> event) {
if (!isEnter(event) || !checkbox->checked()) {
return base::EventFilterResult::Continue;
}
box->uiShow()->show(Ui::MakeConfirmBox({
.text = tr::lng_gigagroup_warning_title(),
.confirmed = [=](Fn<void()> close) {
box->triggerButton(0);
close();
},
.confirmText = tr::lng_box_yes(),
.cancelText = tr::lng_box_no(),
}));
return base::EventFilterResult::Cancel;
});
};
const auto createParticipantsList = [&](
not_null<Controller*> controller) {
const auto wrap = inner->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
inner,
object_ptr<Ui::VerticalLayout>(inner)));
wrap->toggle(false, anim::type::instant);
controller->toggleRequestsFromTop.events(
) | rpl::start_with_next([=](bool toggled) {
wrap->toggle(toggled, anim::type::normal);
}, wrap->lifetime());
const auto container = wrap->entity();
Ui::AddSkip(container);
auto &lifetime = wrap->lifetime();
const auto clicks = lifetime.make_state<rpl::event_stream<>>();
const auto checkboxes = ranges::views::all(
participants
) | ranges::views::transform([&](not_null<PeerData*> peer) {
const auto line = container->add(
object_ptr<Ui::AbstractButton>(container));
const auto &st = st::moderateBoxUserpic;
line->resize(line->width(), st.size.height());
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
line,
peer,
st);
const auto checkbox = Ui::CreateChild<Ui::Checkbox>(
line,
peer->name(),
false,
st::defaultBoxCheckbox);
line->widthValue(
) | rpl::start_with_next([=](int width) {
userpic->moveToLeft(
st::boxRowPadding.left()
+ checkbox->checkRect().width()
+ st::defaultBoxCheckbox.textPosition.x(),
0);
const auto skip = st::defaultBoxCheckbox.textPosition.x();
checkbox->resizeToWidth(width
- rect::right(userpic)
- skip
- st::boxRowPadding.right());
checkbox->moveToLeft(
rect::right(userpic) + skip,
((userpic->height() - checkbox->height()) / 2)
+ st::defaultBoxCheckbox.margin.top());
}, checkbox->lifetime());
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
checkbox->setAttribute(Qt::WA_TransparentForMouseEvents);
line->setClickedCallback([=] {
checkbox->setChecked(!checkbox->checked());
clicks->fire({});
});
return checkbox;
}) | ranges::to_vector;
clicks->events(
) | rpl::start_with_next([=] {
controller->toggleRequestsFromInner.fire_copy(
ranges::any_of(checkboxes, &Ui::Checkbox::checked));
}, container->lifetime());
controller->checkAllRequests.events(
) | rpl::start_with_next([=](bool checked) {
for (const auto &c : checkboxes) {
c->setChecked(checked);
}
}, container->lifetime());
controller->collectRequests = [=] {
auto result = Participants();
for (auto i = 0; i < checkboxes.size(); i++) {
if (checkboxes[i]->checked()) {
result.push_back(participants[i]);
}
}
return result;
};
};
const auto appendList = [&](
not_null<Ui::Checkbox*> checkbox,
not_null<Controller*> controller) {
if (isSingle) {
const auto p = participants.front();
controller->collectRequests = [=] { return Participants{ p }; };
return;
}
const auto count = int(participants.size());
const auto button = Ui::CreateChild<Button>(inner, count);
button->resize(Button::ComputeSize(count));
const auto overlay = Ui::CreateChild<Ui::AbstractButton>(inner);
checkbox->geometryValue(
) | rpl::start_with_next([=](const QRect &rect) {
overlay->setGeometry(rect);
overlay->raise();
button->moveToRight(
st::moderateBoxExpandRight,
rect.top() + (rect.height() - button->height()) / 2,
box->width());
button->raise();
}, button->lifetime());
controller->toggleRequestsFromInner.events(
) | rpl::start_with_next([=](bool toggled) {
checkbox->setChecked(toggled);
}, checkbox->lifetime());
button->setClickedCallback([=] {
button->setChecked(!button->checked());
controller->toggleRequestsFromTop.fire_copy(button->checked());
});
overlay->setClickedCallback([=] {
checkbox->setChecked(!checkbox->checked());
controller->checkAllRequests.fire_copy(checkbox->checked());
});
createParticipantsList(controller);
};
Ui::AddSkip(inner);
const auto title = box->addRow(
object_ptr<Ui::FlatLabel>(
box,
(items.size() == 1)
? tr::lng_selected_delete_sure_this()
: tr::lng_selected_delete_sure(
lt_count,
rpl::single(items.size()) | tr::to_count()),
st::boxLabel));
Ui::AddSkip(inner);
Ui::AddSkip(inner);
Ui::AddSkip(inner);
{
const auto report = box->addRow(
object_ptr<Ui::Checkbox>(
box,
tr::lng_report_spam(tr::now),
false,
st::defaultBoxCheckbox),
st::boxRowPadding + buttonPadding);
const auto controller = box->lifetime().make_state<Controller>();
appendList(report, controller);
handleSubmition(report);
const auto ids = items.front()->from()->owner().itemsToIds(items);
handleConfirmation(report, controller, [=](
not_null<PeerData*> p,
not_null<ChannelData*> c) {
auto filtered = ranges::views::all(
ids
) | ranges::views::transform([](const FullMsgId &id) {
return MTP_int(id.msg);
}) | ranges::to<QVector<MTPint>>();
c->session().api().request(
MTPchannels_ReportSpam(
c->inputChannel,
p->input,
MTP_vector<MTPint>(std::move(filtered)))
).send();
});
}
if (allCanDelete) {
Ui::AddSkip(inner);
Ui::AddSkip(inner);
const auto deleteAll = inner->add(
object_ptr<Ui::Checkbox>(
inner,
!(isSingle)
? tr::lng_delete_all_from_users(
tr::now,
Ui::Text::WithEntities)
: tr::lng_delete_all_from_user(
tr::now,
lt_user,
Ui::Text::Bold(items.front()->from()->name()),
Ui::Text::WithEntities),
false,
st::defaultBoxCheckbox),
st::boxRowPadding + buttonPadding);
if (isSingle) {
const auto history = items.front()->history();
tr::lng_selected_delete_sure(
lt_count,
rpl::combine(
MessagesCountValue(history, participants.front()),
deleteAll->checkedValue()
) | rpl::map([s = items.size()](int all, bool checked) {
return float64((checked && all) ? all : s);
})
) | rpl::start_with_next([=](const QString &text) {
title->setText(text);
title->resizeToWidth(inner->width()
- rect::m::sum::h(st::boxRowPadding));
}, title->lifetime());
}
const auto controller = box->lifetime().make_state<Controller>();
appendList(deleteAll, controller);
handleSubmition(deleteAll);
handleConfirmation(deleteAll, controller, [=](
not_null<PeerData*> p,
not_null<ChannelData*> c) {
p->session().api().deleteAllFromParticipant(c, p);
});
}
if (allCanBan) {
auto ownedWrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
inner,
object_ptr<Ui::VerticalLayout>(inner));
Ui::AddSkip(inner);
Ui::AddSkip(inner);
const auto ban = inner->add(
object_ptr<Ui::Checkbox>(
box,
rpl::conditional(
ownedWrap->toggledValue(),
tr::lng_context_restrict_user(),
rpl::conditional(
rpl::single(isSingle),
tr::lng_ban_user(),
tr::lng_ban_users())),
false,
st::defaultBoxCheckbox),
st::boxRowPadding + buttonPadding);
const auto controller = box->lifetime().make_state<Controller>();
appendList(ban, controller);
handleSubmition(ban);
Ui::AddSkip(inner);
Ui::AddSkip(inner);
const auto wrap = inner->add(std::move(ownedWrap));
const auto container = wrap->entity();
wrap->toggle(false, anim::type::instant);
const auto session = &participants.front()->session();
const auto emojiMargin = QMargins(
-st::moderateBoxExpandInnerSkip,
-st::moderateBoxExpandInnerSkip / 2,
0,
0);
const auto emojiUp = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIcon,
emojiMargin,
false));
const auto emojiDown = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIconDown,
emojiMargin,
false));
auto label = object_ptr<Ui::FlatLabel>(
inner,
QString(),
st::moderateBoxDividerLabel);
const auto raw = label.data();
auto &lifetime = wrap->lifetime();
const auto scrollLifetime = lifetime.make_state<rpl::lifetime>();
label->setClickHandlerFilter([=](
const ClickHandlerPtr &handler,
Qt::MouseButton button) {
if (button != Qt::LeftButton) {
return false;
}
wrap->toggle(!wrap->toggled(), anim::type::normal);
{
inner->heightValue() | rpl::start_with_next([=] {
if (!wrap->animating()) {
scrollLifetime->destroy();
Ui::PostponeCall(crl::guard(box, [=] {
box->scrollToY(std::numeric_limits<int>::max());
}));
} else {
box->scrollToY(std::numeric_limits<int>::max());
}
}, *scrollLifetime);
}
return true;
});
wrap->toggledValue(
) | rpl::map([isSingle, emojiUp, emojiDown](bool toggled) {
return ((toggled && isSingle)
? tr::lng_restrict_user_part
: (toggled && !isSingle)
? tr::lng_restrict_users_part
: isSingle
? tr::lng_restrict_user_full
: tr::lng_restrict_users_full)(
lt_emoji,
rpl::single(toggled ? emojiUp : emojiDown),
Ui::Text::WithEntities);
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(
Ui::Text::Link(text, u"internal:"_q),
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { raw->update(); },
});
}, label->lifetime());
Ui::AddSkip(inner);
inner->add(object_ptr<Ui::DividerLabel>(
inner,
std::move(label),
st::defaultBoxDividerLabelPadding,
RectPart::Top | RectPart::Bottom));
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
const auto peer = items.front()->history()->peer;
const auto chat = peer->asChat();
const auto channel = peer->asChannel();
const auto defaultRestrictions = chat
? chat->defaultRestrictions()
: channel->defaultRestrictions();
const auto prepareFlags = FixDependentRestrictions(
defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::ChangeInfo | Flag::PinMessages)
: Flags(0)));
const auto disabledMessages = [&] {
auto result = base::flat_map<Flags, QString>();
{
const auto disabled = FixDependentRestrictions(
defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::ChangeInfo | Flag::PinMessages)
: Flags(0)));
result.emplace(
disabled,
tr::lng_rights_restriction_for_all(tr::now));
}
return result;
}();
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
box,
rpl::conditional(
rpl::single(isSingle),
tr::lng_restrict_users_part_single_header(),
tr::lng_restrict_users_part_header(
lt_count,
rpl::single(participants.size()) | tr::to_count())),
prepareFlags,
disabledMessages,
{ .isForum = peer->isForum() });
std::move(changes) | rpl::start_with_next([=] {
ban->setChecked(true);
}, ban->lifetime());
Ui::AddSkip(container);
Ui::AddDivider(container);
Ui::AddSkip(container);
container->add(std::move(checkboxes));
// Handle confirmation manually.
confirms->events() | rpl::start_with_next([=] {
if (ban->checked() && controller->collectRequests) {
const auto kick = !wrap->toggled();
const auto restrictions = getRestrictions();
const auto request = [=](
not_null<PeerData*> peer,
not_null<ChannelData*> channel) {
if (!kick) {
Api::ChatParticipants::Restrict(
channel,
peer,
ChatRestrictionsInfo(), // Unused.
ChatRestrictionsInfo(restrictions, 0),
nullptr,
nullptr);
} else {
channel->session().api().chatParticipants().kick(
channel,
peer,
{ channel->restrictions(), 0 });
}
};
sequentiallyRequest(request, controller->collectRequests());
}
}, ban->lifetime());
}
const auto close = crl::guard(box, [=] { box->closeBox(); });
{
const auto data = &participants.front()->session().data();
const auto ids = data->itemsToIds(items);
box->addButton(tr::lng_box_delete(), [=] {
confirms->fire({});
if (confirmed) {
confirmed();
}
data->histories().deleteMessages(ids, true);
data->sendHistoryChangeNotifications();
close();
});
}
box->addButton(tr::lng_cancel(), close);
}
bool CanCreateModerateMessagesBox(const HistoryItemsList &items) {
const auto options = CalculateModerateOptions(items);
return (options.allCanBan || options.allCanDelete)
&& !options.participants.empty();
}
void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
const auto container = box->verticalLayout();
const auto maybeUser = peer->asUser();
Ui::AddSkip(container);
Ui::AddSkip(container);
base::install_event_filter(box, [=](not_null<QEvent*> event) {
if (event->type() == QEvent::KeyPress) {
if (const auto k = static_cast<QKeyEvent*>(event.get())) {
if ((k->key() == Qt::Key_Enter)
|| (k->key() == Qt::Key_Return)) {
box->uiShow()->show(Ui::MakeConfirmBox({
.text = tr::lng_gigagroup_warning_title(),
.confirmed = [=](Fn<void()> close) {
box->triggerButton(0);
close();
},
.confirmText = tr::lng_box_yes(),
.cancelText = tr::lng_box_no(),
}));
}
}
}
return base::EventFilterResult::Continue;
});
const auto line = container->add(object_ptr<Ui::RpWidget>(container));
const auto &st = st::mainMenuUserpic;
line->resize(line->width(), st.size.height());
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
line,
peer,
st);
userpic->showSavedMessagesOnSelf(true);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
line,
peer->isSelf()
? tr::lng_saved_messages() | Ui::Text::ToBold()
: maybeUser
? tr::lng_profile_delete_conversation() | Ui::Text::ToBold()
: rpl::single(Ui::Text::Bold(peer->name())) | rpl::type_erased(),
box->getDelegate()->style().title);
line->widthValue(
) | rpl::start_with_next([=](int width) {
userpic->moveToLeft(st::boxRowPadding.left(), 0);
const auto skip = st::defaultBoxCheckbox.textPosition.x();
label->resizeToWidth(width
- rect::right(userpic)
- skip
- st::boxRowPadding.right());
label->moveToLeft(
rect::right(userpic) + skip,
((userpic->height() - label->height()) / 2));
}, label->lifetime());
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
Ui::AddSkip(container);
Ui::AddSkip(container);
box->addRow(
object_ptr<Ui::FlatLabel>(
container,
peer->isSelf()
? tr::lng_sure_delete_saved_messages()
: maybeUser
? tr::lng_sure_delete_history(
lt_contact,
rpl::single(peer->name()))
: (peer->isChannel() && !peer->isMegagroup())
? tr::lng_sure_leave_channel()
: tr::lng_sure_leave_group(),
st::boxLabel));
const auto maybeCheckbox = [&]() -> Ui::Checkbox* {
if (!peer->canRevokeFullHistory()) {
return nullptr;
}
Ui::AddSkip(container);
Ui::AddSkip(container);
return box->addRow(
object_ptr<Ui::Checkbox>(
container,
maybeUser
? tr::lng_delete_for_other_check(
tr::now,
lt_user,
TextWithEntities{ maybeUser->firstName },
Ui::Text::RichLangValue)
: tr::lng_delete_for_everyone_check(
tr::now,
Ui::Text::WithEntities),
false,
st::defaultBoxCheckbox));
}();
Ui::AddSkip(container);
auto buttonText = maybeUser
? tr::lng_box_delete()
: !maybeCheckbox
? tr::lng_box_leave()
: maybeCheckbox->checkedValue() | rpl::map([](bool checked) {
return checked ? tr::lng_box_delete() : tr::lng_box_leave();
}) | rpl::flatten_latest();
const auto close = crl::guard(box, [=] { box->closeBox(); });
box->addButton(std::move(buttonText), [=] {
const auto revoke = maybeCheckbox && maybeCheckbox->checked();
Core::App().closeChatFromWindows(peer);
// Don't delete old history by default,
// because Android app doesn't.
//
//if (const auto from = peer->migrateFrom()) {
// peer->session().api().deleteConversation(from, false);
//}
peer->session().api().deleteConversation(peer, revoke);
close();
}, st::attentionBoxButton);
box->addButton(tr::lng_cancel(), close);
}
@@ -0,0 +1,23 @@
/*
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
class PeerData;
namespace Ui {
class GenericBox;
} // namespace Ui
void CreateModerateMessagesBox(
not_null<Ui::GenericBox*> box,
const HistoryItemsList &items,
Fn<void()> confirmed);
[[nodiscard]] bool CanCreateModerateMessagesBox(const HistoryItemsList &);
void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer);
+1 -1
View File
@@ -740,7 +740,7 @@ void PasscodeBox::submitOnlyCheckCloudPassword(const QString &oldPassword) {
void PasscodeBox::sendOnlyCheckCloudPassword(const QString &oldPassword) {
checkPassword(oldPassword, [=](const Core::CloudPasswordResult &check) {
if (const auto onstack = _cloudFields.customCheckCallback) {
onstack(check);
onstack(check, Ui::MakeWeak(this));
} else {
Assert(_cloudFields.turningOff);
sendClearCloudPassword(check);
+4 -1
View File
@@ -51,7 +51,10 @@ public:
TimeId pendingResetDate = 0;
// Check cloud password for some action.
Fn<void(const Core::CloudPasswordResult &)> customCheckCallback;
using CustomCheck = Fn<void(
const Core::CloudPasswordResult &,
QPointer<PasscodeBox>)>;
CustomCheck customCheckCallback;
rpl::producer<QString> customTitle;
std::optional<QString> customDescription;
rpl::producer<QString> customSubmitButton;
+106 -30
View File
@@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_widgets.h"
#include <xxhash.h> // XXH64.
#include <QtWidgets/QApplication>
[[nodiscard]] PeerListRowId UniqueRowIdFromString(const QString &d) {
return XXH64(d.data(), d.size() * sizeof(ushort), 0);
@@ -734,6 +735,10 @@ auto PeerListRow::generateNameWords() const
return peer()->nameWords();
}
const style::PeerListItem &PeerListRow::computeSt(
const style::PeerListItem &st) const {
return st;
}
void PeerListRow::invalidatePixmapsCache() {
if (_checkbox) {
@@ -816,9 +821,14 @@ void PeerListRow::stopLastRipple() {
}
}
void PeerListRow::paintRipple(Painter &p, int x, int y, int outerWidth) {
void PeerListRow::paintRipple(
Painter &p,
const style::PeerListItem &st,
int x,
int y,
int outerWidth) {
if (_ripple) {
_ripple->paint(p, x, y, outerWidth);
_ripple->paint(p, x, y, outerWidth, &st.button.ripple.color->c);
if (_ripple->empty()) {
_ripple.reset();
}
@@ -1039,11 +1049,9 @@ void PeerListContent::changeCheckState(
not_null<PeerListRow*> row,
bool checked,
anim::type animated) {
row->setChecked(
checked,
_st.item.checkbox,
animated,
[=] { updateRow(row); });
row->setChecked(checked, _st.item.checkbox, animated, [=] {
updateRow(row);
});
}
void PeerListContent::setRowHidden(not_null<PeerListRow*> row, bool hidden) {
@@ -1545,15 +1553,44 @@ void PeerListContent::handleMouseMove(QPoint globalPosition) {
&& *_lastMousePosition == globalPosition) {
return;
}
if (_trackPressStart
&& ((*_trackPressStart - globalPosition).manhattanLength()
> QApplication::startDragDistance())) {
_trackPressStart = {};
_controller->rowTrackPressCancel();
}
if (!_controller->rowTrackPressSkipMouseSelection()) {
selectByMouse(globalPosition);
}
}
void PeerListContent::pressLeftToContextMenu(bool shown) {
if (shown) {
setContexted(_pressed);
setPressed(Selected());
} else {
setContexted(Selected());
}
}
bool PeerListContent::trackRowPressFromGlobal(QPoint globalPosition) {
selectByMouse(globalPosition);
if (const auto row = getRow(_selected.index)) {
if (_controller->rowTrackPress(row)) {
_trackPressStart = globalPosition;
return true;
}
}
return false;
}
void PeerListContent::mousePressEvent(QMouseEvent *e) {
_pressButton = e->button();
selectByMouse(e->globalPos());
setPressed(_selected);
if (auto row = getRow(_selected.index)) {
auto updateCallback = [this, row, hint = _selected.index] {
_trackPressStart = {};
if (const auto row = getRow(_selected.index)) {
const auto updateCallback = [this, row, hint = _selected.index] {
updateRow(row, hint);
};
if (_selected.element) {
@@ -1579,8 +1616,11 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) {
row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback));
}
}
if (_pressButton == Qt::LeftButton && _controller->rowTrackPress(row)) {
_trackPressStart = e->globalPos();
}
}
if (anim::Disabled() && !_selected.element) {
if (anim::Disabled() && !_trackPressStart && !_selected.element) {
mousePressReleased(e->button());
}
}
@@ -1590,6 +1630,9 @@ void PeerListContent::mouseReleaseEvent(QMouseEvent *e) {
}
void PeerListContent::mousePressReleased(Qt::MouseButton button) {
_trackPressStart = {};
_controller->rowTrackPressCancel();
updateRow(_pressed.index);
updateRow(_selected.index);
@@ -1691,7 +1734,9 @@ crl::time PeerListContent::paintRow(
const auto row = getRow(index);
Assert(row != nullptr);
row->lazyInitialize(_st.item);
const auto &st = row->computeSt(_st.item);
row->lazyInitialize(st);
const auto outerWidth = width();
auto refreshStatusAt = row->refreshStatusTime();
@@ -1719,8 +1764,8 @@ crl::time PeerListContent::paintRow(
const auto opacity = row->opacity();
const auto &bg = selected
? _st.item.button.textBgOver
: _st.item.button.textBg;
? st.button.textBgOver
: st.button.textBg;
if (opacity < 1.) {
p.setOpacity(opacity);
}
@@ -1731,36 +1776,37 @@ crl::time PeerListContent::paintRow(
});
p.fillRect(0, 0, outerWidth, _rowHeight, bg);
row->paintRipple(p, 0, 0, outerWidth);
row->paintRipple(p, st, 0, 0, outerWidth);
row->paintUserpic(
p,
_st.item,
_st.item.photoPosition.x(),
_st.item.photoPosition.y(),
st,
st.photoPosition.x(),
st.photoPosition.y(),
outerWidth);
p.setPen(st::contactsNameFg);
const auto skipRight = _st.item.photoPosition.x();
const auto skipRight = st.photoPosition.x();
const auto rightActionSize = row->rightActionSize();
const auto rightActionMargins = rightActionSize.isEmpty()
? QMargins()
: row->rightActionMargins();
const auto &name = row->name();
const auto namex = _st.item.namePosition.x();
const auto namey = _st.item.namePosition.y();
const auto namePosition = st.namePosition;
const auto namex = namePosition.x();
const auto namey = namePosition.y();
auto namew = outerWidth - namex - skipRight;
if (!rightActionSize.isEmpty()
&& (namey < rightActionMargins.top() + rightActionSize.height())
&& (namey + _st.item.nameStyle.font->height
&& (namey + st.nameStyle.font->height
> rightActionMargins.top())) {
namew -= rightActionMargins.left()
+ rightActionSize.width()
+ rightActionMargins.right()
- skipRight;
}
const auto statusx = _st.item.statusPosition.x();
const auto statusy = _st.item.statusPosition.y();
const auto statusx = st.statusPosition.x();
const auto statusy = st.statusPosition.y();
auto statusw = outerWidth - statusx - skipRight;
if (!rightActionSize.isEmpty()
&& (statusy < rightActionMargins.top() + rightActionSize.height())
@@ -1782,17 +1828,17 @@ crl::time PeerListContent::paintRow(
width(),
selected);
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
p.setPen(anim::pen(_st.item.nameFg, _st.item.nameFgChecked, nameCheckedRatio));
p.setPen(anim::pen(st.nameFg, st.nameFgChecked, nameCheckedRatio));
name.drawLeftElided(p, namex, namey, namew, width());
p.setFont(st::contactsStatusFont);
if (row->isSearchResult()
&& !_mentionHighlight.isEmpty()
&& peer
&& peer->userName().startsWith(
&& peer->username().startsWith(
_mentionHighlight,
Qt::CaseInsensitive)) {
const auto username = peer->userName();
const auto username = peer->username();
const auto availableWidth = statusw;
auto highlightedPart = '@' + username.mid(0, _mentionHighlight.size());
auto grayedPart = username.mid(_mentionHighlight.size());
@@ -1801,17 +1847,17 @@ crl::time PeerListContent::paintRow(
if (highlightedWidth > availableWidth) {
highlightedPart = st::contactsStatusFont->elided(highlightedPart, availableWidth);
}
p.setPen(_st.item.statusFgActive);
p.setPen(st.statusFgActive);
p.drawTextLeft(statusx, statusy, width(), highlightedPart);
} else {
grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth);
p.setPen(_st.item.statusFgActive);
p.setPen(st.statusFgActive);
p.drawTextLeft(statusx, statusy, width(), highlightedPart);
p.setPen(selected ? _st.item.statusFgOver : _st.item.statusFg);
p.setPen(selected ? st.statusFgOver : st.statusFg);
p.drawTextLeft(statusx + highlightedWidth, statusy, width(), grayedPart);
}
} else {
row->paintStatusText(p, _st.item, statusx, statusy, statusw, width(), selected);
row->paintStatusText(p, st, statusx, statusy, statusw, width(), selected);
}
row->elementsPaint(
@@ -1907,10 +1953,30 @@ void PeerListContent::selectSkipPage(int height, int direction) {
selectSkip(rowsToSkip * direction);
}
void PeerListContent::selectLast() {
const auto rowsCount = shownRowsCount();
const auto newSelectedIndex = rowsCount - 1;
_selected.index.value = newSelectedIndex;
_selected.element = 0;
if (newSelectedIndex >= 0) {
auto top = (newSelectedIndex > 0) ? getRowTop(RowIndex(newSelectedIndex)) : 0;
auto bottom = (newSelectedIndex + 1 < rowsCount) ? getRowTop(RowIndex(newSelectedIndex + 1)) : height();
_scrollToRequests.fire({ top, bottom });
}
update();
_selectedIndex = _selected.index.value;
}
rpl::producer<int> PeerListContent::selectedIndexValue() const {
return _selectedIndex.value();
}
int PeerListContent::selectedIndex() const {
return _selectedIndex.current();
}
bool PeerListContent::hasSelection() const {
return _selected.index.value >= 0;
}
@@ -2095,6 +2161,16 @@ bool PeerListContent::submitted() {
return false;
}
PeerListRowId PeerListContent::updateFromParentDrag(QPoint globalPosition) {
selectByMouse(globalPosition);
const auto row = getRow(_selected.index);
return row ? row->id() : 0;
}
void PeerListContent::dragLeft() {
clearSelection();
}
void PeerListContent::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
+35 -1
View File
@@ -100,6 +100,8 @@ public:
-> const base::flat_set<QChar> &;
[[nodiscard]] virtual auto generateNameWords() const
-> const base::flat_set<QString> &;
[[nodiscard]] virtual const style::PeerListItem &computeSt(
const style::PeerListItem &st) const;
virtual void preloadUserpic();
@@ -228,7 +230,12 @@ public:
QPoint point,
UpdateCallback &&updateCallback);
void stopLastRipple();
void paintRipple(Painter &p, int x, int y, int outerWidth);
void paintRipple(
Painter &p,
const style::PeerListItem &st,
int x,
int y,
int outerWidth);
void paintUserpic(
Painter &p,
const style::PeerListItem &st,
@@ -341,6 +348,9 @@ public:
virtual int peerListPartitionRows(Fn<bool(const PeerListRow &a)> border) = 0;
virtual std::shared_ptr<Main::SessionShow> peerListUiShow() = 0;
virtual void peerListPressLeftToContextMenu(bool shown) = 0;
virtual bool peerListTrackRowPressFromGlobal(QPoint globalPosition) = 0;
template <typename PeerDataRange>
void peerListAddSelectedPeers(PeerDataRange &&range) {
for (const auto peer : range) {
@@ -471,6 +481,15 @@ public:
}
}
virtual bool rowTrackPress(not_null<PeerListRow*> row) {
return false;
}
virtual void rowTrackPressCancel() {
}
virtual bool rowTrackPressSkipMouseSelection() {
return false;
}
virtual void loadMoreRows() {
}
virtual void itemDeselectedHook(not_null<PeerData*> peer) {
@@ -601,6 +620,7 @@ public:
};
SkipResult selectSkip(int direction);
void selectSkipPage(int height, int direction);
void selectLast();
enum class Mode {
Default,
@@ -609,6 +629,7 @@ public:
void setMode(Mode mode);
[[nodiscard]] rpl::producer<int> selectedIndexValue() const;
[[nodiscard]] int selectedIndex() const;
[[nodiscard]] bool hasSelection() const;
[[nodiscard]] bool hasPressed() const;
void clearSelection();
@@ -616,6 +637,9 @@ public:
void searchQueryChanged(QString query);
bool submitted();
PeerListRowId updateFromParentDrag(QPoint globalPosition);
void dragLeft();
// Interface for the controller.
void appendRow(std::unique_ptr<PeerListRow> row);
void appendSearchRow(std::unique_ptr<PeerListRow> row);
@@ -643,6 +667,8 @@ public:
void refreshRows();
void mouseLeftGeometry();
void pressLeftToContextMenu(bool shown);
bool trackRowPressFromGlobal(QPoint globalPosition);
void setSearchMode(PeerListSearchMode mode);
void changeCheckState(
@@ -817,6 +843,7 @@ private:
bool _mouseSelection = false;
std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton;
std::optional<QPoint> _trackPressStart;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
@@ -980,6 +1007,13 @@ public:
bool highlightRow,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override;
void peerListPressLeftToContextMenu(bool shown) override {
_content->pressLeftToContextMenu(shown);
}
bool peerListTrackRowPressFromGlobal(QPoint globalPosition) override {
return _content->trackRowPressFromGlobal(globalPosition);
}
protected:
not_null<PeerListContent*> content() const {
return _content;
@@ -42,16 +42,14 @@ namespace {
constexpr auto kDefaultIconId = DocumentId(0x7FFF'FFFF'FFFF'FFFFULL);
struct DefaultIcon {
QString title;
int32 colorId = 0;
};
using DefaultIcon = Data::TopicIconDescriptor;
class DefaultIconEmoji final : public Ui::Text::CustomEmoji {
public:
DefaultIconEmoji(
rpl::producer<DefaultIcon> value,
Fn<void()> repaint);
Fn<void()> repaint,
Data::CustomEmojiSizeTag tag);
int width() override;
QString entityData() override;
@@ -64,14 +62,17 @@ public:
private:
DefaultIcon _icon = {};
QImage _image;
Data::CustomEmojiSizeTag _tag = {};
rpl::lifetime _lifetime;
};
DefaultIconEmoji::DefaultIconEmoji(
rpl::producer<DefaultIcon> value,
Fn<void()> repaint) {
rpl::producer<DefaultIcon> value,
Fn<void()> repaint,
Data::CustomEmojiSizeTag tag)
: _tag(tag) {
std::move(value) | rpl::start_with_next([=](DefaultIcon value) {
_icon = value;
_image = QImage();
@@ -88,15 +89,22 @@ QString DefaultIconEmoji::entityData() {
}
void DefaultIconEmoji::paint(QPainter &p, const Context &context) {
const auto &st = (_tag == Data::CustomEmojiSizeTag::Normal)
? st::normalForumTopicIcon
: st::defaultForumTopicIcon;
if (_image.isNull()) {
_image = Data::ForumTopicIconFrame(
_icon.colorId,
_icon.title,
st::defaultForumTopicIcon);
_image = Data::IsForumGeneralIconTitle(_icon.title)
? Data::ForumTopicGeneralIconFrame(
st.size,
Data::ParseForumGeneralIconColor(_icon.colorId))
: Data::ForumTopicIconFrame(_icon.colorId, _icon.title, st);
}
const auto esize = Ui::Emoji::GetSizeLarge() / style::DevicePixelRatio();
const auto full = (_tag == Data::CustomEmojiSizeTag::Normal)
? Ui::Emoji::GetSizeNormal()
: Ui::Emoji::GetSizeLarge();
const auto esize = full / style::DevicePixelRatio();
const auto customSize = Ui::Text::AdjustCustomEmojiSize(esize);
const auto skip = (customSize - st::defaultForumTopicIcon.size) / 2;
const auto skip = (customSize - st.size) / 2;
p.drawImage(context.position + QPoint(skip, skip), _image);
}
@@ -212,7 +220,7 @@ bool DefaultIconEmoji::readyInDefaultState() {
) | rpl::start_with_next([=] {
state->frame = Data::ForumTopicGeneralIconFrame(
st::largeForumTopicIcon.size,
st::windowSubTextFg);
st::windowSubTextFg->c);
result->update();
}, result->lifetime());
@@ -261,7 +269,8 @@ struct IconSelector {
if (id == kDefaultIconId) {
return std::make_unique<DefaultIconEmoji>(
rpl::duplicate(defaultIcon),
repaint);
std::move(repaint),
tag);
}
return manager->create(id, std::move(repaint), tag);
};
@@ -572,3 +581,13 @@ void EditForumTopicBox(
box->closeBox();
});
}
std::unique_ptr<Ui::Text::CustomEmoji> MakeTopicIconEmoji(
Data::TopicIconDescriptor descriptor,
Fn<void()> repaint,
Data::CustomEmojiSizeTag tag) {
return std::make_unique<DefaultIconEmoji>(
rpl::single(descriptor),
std::move(repaint),
tag);
}

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