Compare commits

..

68 Commits

Author SHA1 Message Date
John Preston
c37b08ac8b Version 3.7.2.
- Fix mute period selector values.
- Fix a crash in repeated context menu item selection.
- Fix context menu item selection of systems without a compositor.
2022-04-25 22:38:29 +04:00
Hugo Osvaldo Barrera
c52a5927e5 Avoid a second query for the current color-scheme
Telegram listens for a signal that indicates when the color-scheme
changes. The signal itself includes the new value, but Telegram
currently queries for the value immediately after getting the signal.
This second round-trip is unnecessary, since the signal itself contains
the same information.

This changeset avoids this follow-up query, and drops the now-unused
`Setter`.
2022-04-25 22:38:08 +04:00
23rd
edcfac8da3 Slightly improved display of media replacement in admin log. 2022-04-25 22:35:02 +04:00
23rd
a994c9f017 Moved EditPeerHistoryVisibilityBox to td_ui. 2022-04-25 22:35:02 +04:00
23rd
66e6bf8217 Replaced EditPeerHistoryVisibilityBox with generic box. 2022-04-25 22:35:02 +04:00
23rd
4a4cc766c2 Replaced icons in manage group / channel. 2022-04-25 22:35:02 +04:00
23rd
31cd841b75 Added bot button to bar of pinned messages. 2022-04-25 22:35:02 +04:00
23rd
1710890886 Added ability to change width between pinned bar animation entries. 2022-04-25 22:35:02 +04:00
23rd
16f616c5e0 Added ability to set content to bar of pinned messages later. 2022-04-25 22:35:02 +04:00
23rd
7600c9bb2f Added fade animation to right button in bar of pinned messages. 2022-04-25 22:35:02 +04:00
23rd
100a44daef Removed unused includes from MultiSelect. 2022-04-25 22:35:02 +04:00
23rd
54305fafde Removed forced context menu in profiles for muted peers. 2022-04-25 22:35:02 +04:00
23rd
d172d3d7db Fixed intervals of seconds in PickMuteBox. 2022-04-25 22:35:02 +04:00
Ilya Fedin
cee593c423 Check whether notification image has alpha channel 2022-04-25 22:33:22 +04:00
John Preston
43adbb1cb1 Revert some changes in Menu actions triggering. 2022-04-25 15:54:32 +04:00
John Preston
e96731be11 Fix popup menu callbacks on systems without compositing. 2022-04-25 15:42:42 +04:00
John Preston
6ea062462f Fix crash in Ui::Menu second action trigger event. 2022-04-25 14:03:57 +04:00
John Preston
1bc8d6fb18 Fix non-working Qt-on-Windows bug workaround. 2022-04-25 14:03:43 +04:00
John Preston
73d00a4caf Reload stale video chat on join. 2022-04-25 13:41:24 +04:00
John Preston
a23561c380 Reload stale video chats on group / channel open. 2022-04-25 12:50:58 +04:00
Ilya Fedin
bb75a6a31b Speed up submodule checkout in Dockerfile
Use --depth=1 for submodules, too.
This also replaces perl init-repository for Qt as the only thing it does is fetches submodules, but there's no way to specify --depth=1 with it.
2022-04-24 07:26:20 +04:00
John Preston
ce79c1f0c4 Handle "web_app_request_theme" event in WebView. 2022-04-21 10:47:21 +04:00
John Preston
3cdb82a0bf Version 3.7.1.
- Hardware accelerated video decoding off by default.
- Fix several crashes.
2022-04-20 13:56:09 +04:00
John Preston
d2f928f0c3 Fix info layer animations. 2022-04-20 13:53:07 +04:00
John Preston
3cc0110464 Fix menu callbacks triggering in some cases. 2022-04-20 11:43:53 +04:00
John Preston
df533f2efe Don't use WebView embed in Windows before 8.1. 2022-04-20 11:43:53 +04:00
John Preston
2529bd3f44 Add logging of PickMuteBox invocation. 2022-04-20 11:43:53 +04:00
23rd
a5c12065af Slightly improved style of ttl button. 2022-04-19 17:48:48 +03:00
23rd
101e795af8 Changed time picker box to highlight closest value. 2022-04-19 17:48:48 +03:00
23rd
8faa65fdf3 Improved format of ttl and mute phrases. 2022-04-19 17:48:48 +03:00
John Preston
644881bd3e Fix build on Windows. 2022-04-19 18:13:27 +04:00
John Preston
efa1b2dcbc Update WebView2 package version. 2022-04-19 16:59:23 +04:00
John Preston
92a9832337 Update patches revision in CentOS docker. 2022-04-19 16:21:18 +04:00
John Preston
8f3456cd6c Attempt to fix the build on GCC. 2022-04-19 16:10:45 +04:00
John Preston
e67192cdf0 Fix export window size.
Fixes #24373.

SeparatePanel::show calls activePopupWidget::close,
activePopupWidget::close calls SeparatePanel::resizeEvents with strange values.
2022-04-19 12:02:54 +04:00
John Preston
9f2683a35b Fix crash in MessagesSearch requests. 2022-04-19 12:02:11 +04:00
Ilya Fedin
0a7e25e45a Update cmake_helpers 2022-04-19 10:23:24 +04:00
Ilya Fedin
643a034aae Fix default branch check in the Dokcer action 2022-04-19 10:23:24 +04:00
John Preston
1c5a3aef54 Hardware accelerated video decoding off by default. 2022-04-19 09:51:29 +04:00
John Preston
bfe47a1ba2 Clear hw_device_ctx in AVCodecContext. 2022-04-19 09:39:01 +04:00
John Preston
acd76fc97b Clear possible crash in media viewer. 2022-04-19 09:39:01 +04:00
John Preston
78fedce2d5 Fix icon positions in manage group / channel. 2022-04-19 09:39:01 +04:00
23rd
5261e962e2 Removed Ui::show from menu item for poll stopping. 2022-04-19 09:39:01 +04:00
23rd
e4bfd562b5 Fixed phone formatting when app is started from settings. 2022-04-19 09:39:01 +04:00
23rd
d289bbdc5e Added ability to report profile photos.
Fixed #24325.
2022-04-19 09:39:01 +04:00
23rd
2e9e3b3751 Provided parent to report toasts. 2022-04-19 09:39:01 +04:00
23rd
af0a2f182c Removed Ui::show from ShowReportItemsBox. 2022-04-19 09:39:01 +04:00
23rd
e3ac84a849 Moved boxes for reporting messages or peers to separated file. 2022-04-19 09:39:01 +04:00
23rd
6dce8dfa20 Moved api for report messages to separated file. 2022-04-19 09:39:01 +04:00
23rd
eef1da56c8 Slightly optimized box of messages reporting in HistoryWidget. 2022-04-19 09:39:01 +04:00
23rd
e37866d0b9 Added animated reactions in manage of groups / channels. 2022-04-19 09:39:00 +04:00
23rd
1ed7d482ab Added ability to choose precise time for user restriction.
Fixed #3599.
Fixed #6923.
2022-04-19 09:39:00 +04:00
23rd
f1a7db780e Fixed text color of menu item for disabling notifications. 2022-04-19 09:39:00 +04:00
23rd
8591fae031 Added slight nice effect to time picker. 2022-04-19 09:39:00 +04:00
23rd
18b9bba21c Fixed width of time picker for different scales. 2022-04-19 09:39:00 +04:00
Ilya Fedin
580e15dc21 Update cmake_helpers 2022-04-19 09:33:23 +04:00
Ilya Fedin
bf4fc2596a Remove unneeded primary screen fallbacks
QWidget::screen automatically fallbacks to primary screen as the last effort, so this is not needed
2022-04-19 09:33:23 +04:00
Ilya Fedin
9a4d2bc8f9 Make processDpi a constexpr and remove unneeded qreal 2022-04-19 08:40:07 +04:00
Ilya Fedin
62a2277f43 Passthrough QT_FONT_DPI in crash report window just like in the main scaling engine 2022-04-19 08:40:07 +04:00
Ilya Fedin
d11885d48c Update URL to the Docker image in Linux action 2022-04-18 21:21:57 +04:00
Ilya Fedin
c8cec18ad3 Update patches in Dockerfile 2022-04-18 20:17:08 +04:00
Ilya Fedin
86105403bf Automatically update Docker image on GHCR 2022-04-18 20:17:08 +04:00
Ilya Fedin
41288f5ddb Update patches in Dockerfile 2022-04-18 10:06:16 +04:00
Ilya Fedin
9cc1a020f3 Have a variable to control debug info in docker image 2022-04-18 10:06:16 +04:00
Ilya Fedin
68f35e98e0 Have less Docker steps to avoid saving superfluous data 2022-04-18 10:06:16 +04:00
Ilya Fedin
b6c9a1d655 Add glib-networking to snap
It's required by webkit2gtk for correct operation
2022-04-17 13:50:25 +04:00
Ilya Fedin
9b35fa29b8 Remove object files from the resulting Docker image 2022-04-17 09:10:44 +04:00
Ilya Fedin
53272d951b Adjust path variables in Dockerfile 2022-04-17 09:10:44 +04:00
112 changed files with 1519 additions and 1268 deletions

View File

@@ -15,6 +15,9 @@ jobs:
name: Ubuntu
runs-on: ubuntu-latest
env:
IMAGE_TAG: ghcr.io/${{ github.repository }}/centos_env:latest
steps:
- name: Clone.
uses: actions/checkout@v2
@@ -22,4 +25,10 @@ jobs:
submodules: recursive
- name: Docker image build.
run: docker build -t telegram_desktop Telegram/build/docker/centos_env
run: docker build -t $IMAGE_TAG --build-arg DEBUG= Telegram/build/docker/centos_env
- name: Push the Docker image.
if: ${{ github.ref_name == github.event.repository.default_branch }}
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
docker push $IMAGE_TAG

View File

@@ -46,7 +46,7 @@ jobs:
name: CentOS 7
runs-on: ubuntu-latest
container:
image: docker.pkg.github.com/telegramdesktop/tdesktop/centos_env
image: ghcr.io/${{ github.repository }}/centos_env
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -137,6 +137,8 @@ PRIVATE
api/api_peer_photo.h
api/api_polls.cpp
api/api_polls.h
api/api_report.cpp
api/api_report.h
api/api_ringtones.cpp
api/api_ringtones.h
api/api_self_destruct.cpp
@@ -186,8 +188,6 @@ PRIVATE
boxes/peers/edit_peer_invite_link.h
boxes/peers/edit_peer_invite_links.cpp
boxes/peers/edit_peer_invite_links.h
boxes/peers/edit_peer_history_visibility_box.cpp
boxes/peers/edit_peer_history_visibility_box.h
boxes/peers/edit_peer_permissions_box.cpp
boxes/peers/edit_peer_permissions_box.h
boxes/peers/edit_peer_reactions.cpp
@@ -258,6 +258,8 @@ PRIVATE
boxes/pin_messages_box.h
boxes/reactions_settings_box.cpp
boxes/reactions_settings_box.h
boxes/report_messages_box.cpp
boxes/report_messages_box.h
boxes/ringtones_box.cpp
boxes/ringtones_box.h
boxes/self_destruction_box.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 B

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1141,6 +1141,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_report_group_title" = "Report group";
"lng_report_bot_title" = "Report bot";
"lng_report_message_title" = "Report message";
"lng_report_profile_photo_title" = "Report profile photo";
"lng_report_profile_video_title" = "Report profile video";
"lng_report_please_select_messages" = "Please select messages to report.";
"lng_report_select_messages" = "Select messages";
"lng_report_messages_none" = "Select Messages";
@@ -1974,7 +1976,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_try_other_contact" = "Try someone else";
"lng_create_group_link" = "Link";
"lng_create_group_invite_link" = "Invite link";
"lng_create_group_description" = "Description (optional)";
"lng_create_group_description" = "Add description...";
"lng_drag_images_here" = "Drop images here";
"lng_drag_photos_here" = "Drop photos here";
@@ -2053,6 +2055,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_mediaview_yesterday" = "yesterday at {time}";
"lng_mediaview_date_time" = "{date} at {time}";
"lng_mediaview_set_userpic" = "Set as Main";
"lng_mediaview_report_profile_photo" = "Report";
"lng_mediaview_saved_to" = "Image was saved to your {downloads} folder";
"lng_mediaview_downloads" = "Downloads";
@@ -2145,6 +2148,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_payments_webview_install_webkit" = "Please install WebKitGTK (webkit2gtk-5.0/webkit2gtk-4.1/webkit2gtk-4.0) using your package manager.";
"lng_payments_webview_switch_mutter" = "Qt's window embedding doesn't work well with Mutter window manager. Please switch to another window manager or desktop environment.";
"lng_payments_webview_switch_wayland" = "There is no way to embed WebView window on Wayland. Please switch to X11.";
"lng_payments_webview_update_windows" = "Please update your system to Windows 8.1 or later.";
"lng_payments_sure_close" = "Are you sure you want to close this payment form? The changes you made will be lost.";
"lng_payments_receipt_label" = "Receipt";
"lng_payments_receipt_label_test" = "Test receipt";
@@ -2657,7 +2661,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_pinned_message" = "{from} pinned this message:";
"lng_admin_log_unpinned_message" = "{from} unpinned this message";
"lng_admin_log_edited_caption" = "{from} edited caption:";
"lng_admin_log_removed_caption" = "{from} removed caption";
"lng_admin_log_edited_media" = "{from} edited media:";
"lng_admin_log_edited_media_and_caption" = "{from} edited media and caption:";
"lng_admin_log_edited_media_and_removed_caption" = "{from} edited media and removed caption:";
"lng_admin_log_removed_caption" = "{from} removed caption:";
"lng_admin_log_previous_caption" = "Original caption";
"lng_admin_log_edited_message" = "{from} edited this message:";
"lng_admin_log_previous_message" = "Original message";

View File

@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="3.7.0.0" />
Version="3.7.2.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,7,0,0
PRODUCTVERSION 3,7,0,0
FILEVERSION 3,7,2,0
PRODUCTVERSION 3,7,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "3.7.0.0"
VALUE "FileVersion", "3.7.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.7.0.0"
VALUE "ProductVersion", "3.7.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,7,0,0
PRODUCTVERSION 3,7,0,0
FILEVERSION 3,7,2,0
PRODUCTVERSION 3,7,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "3.7.0.0"
VALUE "FileVersion", "3.7.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.7.0.0"
VALUE "ProductVersion", "3.7.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -17,10 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
namespace Api {
namespace {
MessageIdsList HistoryItemsFromTL(
[[nodiscard]] MessageIdsList HistoryItemsFromTL(
not_null<Data::Session*> data,
const QVector<MTPMessage> &messages) {
auto result = MessageIdsList();
@@ -45,8 +44,12 @@ MessageIdsList HistoryItemsFromTL(
} // namespace
MessagesSearch::MessagesSearch(not_null<History*> history)
: _history(history)
, _api(&history->session().mtp()) {
: _history(history) {
}
MessagesSearch::~MessagesSearch() {
_history->owner().histories().cancelRequest(
base::take(_searchInHistoryRequest));
}
void MessagesSearch::searchMessages(const QString &query, PeerData *from) {
@@ -78,7 +81,7 @@ void MessagesSearch::searchRequest() {
const auto flags = _from
? MTP_flags(MTPmessages_Search::Flag::f_from_id)
: MTP_flags(0);
_requestId = _api.request(MTPmessages_Search(
_requestId = _history->session().api().request(MTPmessages_Search(
flags,
_history->peer->input,
MTP_string(_query),
@@ -102,10 +105,11 @@ void MessagesSearch::searchRequest() {
}).fail([=](const MTP::Error &error, mtpRequestId id) {
_searchInHistoryRequest = 0;
if (_requestId == id) {
_requestId = 0;
}
if (error.type() == u"SEARCH_QUERY_EMPTY"_q) {
_messagesFounds.fire({ 0, MessageIdsList(), nextToken });
} else if (_requestId == id) {
_requestId = 0;
}
finish();

View File

@@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "mtproto/sender.h"
class HistoryItem;
class History;
class PeerData;
@@ -24,6 +22,7 @@ struct FoundMessages {
class MessagesSearch final {
public:
explicit MessagesSearch(not_null<History*> history);
~MessagesSearch();
void searchMessages(const QString &query, PeerData *from);
void searchMore();
@@ -39,7 +38,6 @@ private:
const QString &nextToken);
const not_null<History*> _history;
MTP::Sender _api;
base::flat_map<QString, TLMessages> _cacheOfStartByToken;

View File

@@ -18,11 +18,10 @@ bool MessagesSearchMerged::RequestCompare::operator()(
}
MessagesSearchMerged::MessagesSearchMerged(not_null<History*> history)
: _apiSearch(history)
, _migratedSearch(history->migrateFrom()
? std::make_optional<MessagesSearch>(history->migrateFrom())
: std::nullopt) {
: _apiSearch(history) {
if (const auto migrated = history->migrateFrom()) {
_migratedSearch.emplace(migrated);
}
const auto checkWaitingForTotal = [=] {
if (_waitingForTotal) {
if (_concatedFound.total >= 0 && _migratedFirstFound.total >= 0) {

View File

@@ -0,0 +1,78 @@
/*
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_report.h"
#include "apiwrap.h"
#include "data/data_peer.h"
#include "data/data_photo.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "ui/boxes/report_box.h"
#include "ui/toast/toast.h"
namespace Api {
namespace {
MTPreportReason ReasonToTL(const Ui::ReportReason &reason) {
using Reason = Ui::ReportReason;
switch (reason) {
case Reason::Spam: return MTP_inputReportReasonSpam();
case Reason::Fake: return MTP_inputReportReasonFake();
case Reason::Violence: return MTP_inputReportReasonViolence();
case Reason::ChildAbuse: return MTP_inputReportReasonChildAbuse();
case Reason::Pornography: return MTP_inputReportReasonPornography();
case Reason::Copyright: return MTP_inputReportReasonCopyright();
case Reason::IllegalDrugs: return MTP_inputReportReasonIllegalDrugs();
case Reason::PersonalDetails:
return MTP_inputReportReasonPersonalDetails();
case Reason::Other: return MTP_inputReportReasonOther();
}
Unexpected("Bad reason group value.");
}
} // namespace
void SendReport(
not_null<QWidget*> toastParent,
not_null<PeerData*> peer,
Ui::ReportReason reason,
const QString &comment,
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data) {
auto done = [=] {
Ui::Toast::Show(toastParent, tr::lng_report_thanks(tr::now));
};
v::match(data, [&](v::null_t) {
peer->session().api().request(MTPaccount_ReportPeer(
peer->input,
ReasonToTL(reason),
MTP_string(comment)
)).done(std::move(done)).send();
}, [&](const MessageIdsList &ids) {
auto apiIds = QVector<MTPint>();
apiIds.reserve(ids.size());
for (const auto &fullId : ids) {
apiIds.push_back(MTP_int(fullId.msg));
}
peer->session().api().request(MTPmessages_Report(
peer->input,
MTP_vector<MTPint>(apiIds),
ReasonToTL(reason),
MTP_string(comment)
)).done(std::move(done)).send();
}, [&](not_null<PhotoData*> photo) {
peer->session().api().request(MTPaccount_ReportProfilePhoto(
peer->input,
photo->mtpInput(),
ReasonToTL(reason),
MTP_string(comment)
)).done(std::move(done)).send();
});
}
} // namespace Api

View File

@@ -0,0 +1,26 @@
/*
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;
class PhotoData;
namespace Ui {
enum class ReportReason;
} // namespace Ui
namespace Api {
void SendReport(
not_null<QWidget*> toastParent,
not_null<PeerData*> peer,
Ui::ReportReason reason,
const QString &comment,
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data);
} // namespace Api

View File

@@ -20,10 +20,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/text/text_utilities.h"
#include "ui/text/text_options.h"
#include "ui/boxes/calendar_box.h"
#include "ui/special_buttons.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "settings/settings_privacy_security.h"
#include "ui/boxes/choose_date_time.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/passcode_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
@@ -510,7 +510,8 @@ not_null<Ui::SlideWrap<Ui::RpWidget>*> EditAdminBox::setupTransferButton(
: tr::lng_rights_transfer_channel)(),
rpl::single(QString()),
[=] { transferOwnership(); },
st::peerPermissionsButton));
st::peerPermissionsButton,
{}));
return wrap;
}
@@ -783,35 +784,33 @@ ChatRestrictionsInfo EditRestrictedBox::defaultRights() const {
}
void EditRestrictedBox::showRestrictUntil() {
auto tomorrow = QDate::currentDate().addDays(1);
auto highlighted = isUntilForever()
? tomorrow
: base::unixtime::parse(getRealUntilValue()).date();
auto month = highlighted;
auto box = Box<Ui::CalendarBox>(Ui::CalendarBoxArgs{
.month = month,
.highlighted = highlighted,
.callback = [=](const QDate &date) {
setRestrictUntil(
static_cast<int>(date.startOfDay().toSecsSinceEpoch()));
},
.finalize = [=](not_null<Ui::CalendarBox*> box) {
box->addLeftButton(
tr::lng_rights_chat_banned_forever(),
[=] { setRestrictUntil(0); });
},
.minDate = tomorrow,
.maxDate = QDate::currentDate().addDays(kMaxRestrictDelayDays),
});
_restrictUntilBox = Ui::MakeWeak(box.data());
_show.showBox(std::move(box));
_show.showBox(Box([=](not_null<Ui::GenericBox*> box) {
const auto save = [=](TimeId result) {
if (!result) {
return;
}
setRestrictUntil(result);
box->closeBox();
};
const auto now = base::unixtime::now();
const auto time = isUntilForever()
? (now + kSecondsInDay)
: getRealUntilValue();
ChooseDateTimeBox(box, {
.title = tr::lng_rights_chat_banned_until_header(),
.submit = tr::lng_settings_save(),
.done = save,
.min = [=] { return now; },
.time = time,
.max = [=] {
return now + kSecondsInDay * kMaxRestrictDelayDays;
},
});
}));
}
void EditRestrictedBox::setRestrictUntil(TimeId until) {
_until = until;
if (_restrictUntilBox) {
_restrictUntilBox->closeBox();
}
_untilVariants.clear();
createUntilGroup();
createUntilVariants();
@@ -861,8 +860,7 @@ void EditRestrictedBox::createUntilVariants() {
tr::lng_rights_chat_banned_custom_date(
tr::now,
lt_date,
langDayOfMonthFull(
base::unixtime::parse(until).date())));
langDateTime(base::unixtime::parse(until))));
}
};
auto addCurrentVariant = [&](TimeId from, TimeId to) {

View File

@@ -17,7 +17,6 @@ class LinkButton;
class Checkbox;
class Radiobutton;
class RadiobuttonGroup;
class CalendarBox;
class VerticalLayout;
template <typename Widget>
class SlideWrap;
@@ -176,7 +175,6 @@ private:
std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
std::vector<base::unique_qptr<Ui::Radiobutton>> _untilVariants;
QPointer<Ui::CalendarBox> _restrictUntilBox;
static constexpr auto kUntilOneDay = -1;
static constexpr auto kUntilOneWeek = -2;

View File

@@ -7,125 +7,56 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/edit_peer_history_visibility_box.h"
#include "boxes/peers/edit_peer_permissions_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_peer.h"
#include "lang/lang_keys.h"
#include "ui/layers/generic_box.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_layers.h"
#include "styles/style_info.h"
namespace {
void EditPeerHistoryVisibilityBox(
not_null<Ui::GenericBox*> box,
bool isLegacy,
Fn<void(HistoryVisibility)> savedCallback,
HistoryVisibility historyVisibilitySavedValue) {
const auto historyVisibility = std::make_shared<
Ui::RadioenumGroup<HistoryVisibility>
>(historyVisibilitySavedValue);
void AddRadioButton(
not_null<Ui::VerticalLayout*> container,
HistoryVisibility value,
const QString &groupText,
rpl::producer<QString> groupAbout,
std::shared_ptr<Ui::RadioenumGroup<HistoryVisibility>> historyVisibility) {
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::editPeerHistoryVisibilityTopSkip));
container->add(object_ptr<Ui::Radioenum<HistoryVisibility>>(
container,
box->setTitle(tr::lng_manage_history_visibility_title());
box->addButton(tr::lng_settings_save(), [=] {
savedCallback(historyVisibility->value());
box->closeBox();
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
box->addSkip(st::editPeerHistoryVisibilityTopSkip);
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>(
box,
historyVisibility,
value,
groupText,
st::defaultBoxCheckbox));
container->add(object_ptr<Ui::PaddingWrap<Ui::FlatLabel>>(
container,
object_ptr<Ui::FlatLabel>(
container,
std::move(groupAbout),
st::editPeerPrivacyLabel),
st::editPeerPreHistoryLabelMargins));
}
void FillContent(
not_null<Ui::VerticalLayout*> parent,
not_null<PeerData*> peer,
std::shared_ptr<Ui::RadioenumGroup<HistoryVisibility>> historyVisibility,
HistoryVisibility savedValue) {
const auto canEdit = [&] {
if (const auto chat = peer->asChat()) {
return chat->canEditPreHistoryHidden();
} else if (const auto channel = peer->asChannel()) {
return channel->canEditPreHistoryHidden();
}
Unexpected("User in HistoryVisibilityEdit.");
}();
if (!canEdit) {
return;
}
historyVisibility->setValue(savedValue);
const auto result = parent->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
parent,
object_ptr<Ui::VerticalLayout>(parent),
st::editPeerHistoryVisibilityMargins));
const auto container = result->entity();
Assert(historyVisibility != nullptr);
AddRadioButton(
container,
HistoryVisibility::Visible,
tr::lng_manage_history_visibility_shown(tr::now),
tr::lng_manage_history_visibility_shown_about(),
historyVisibility);
AddRadioButton(
container,
st::defaultBoxCheckbox));
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_manage_history_visibility_shown_about(),
st::editPeerPrivacyLabel),
st::editPeerPreHistoryLabelMargins + st::boxRowPadding);
box->addSkip(st::editPeerHistoryVisibilityTopSkip);
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>(
box,
historyVisibility,
HistoryVisibility::Hidden,
tr::lng_manage_history_visibility_hidden(tr::now),
(peer->isChat()
? tr::lng_manage_history_visibility_hidden_legacy
: tr::lng_manage_history_visibility_hidden_about)(),
historyVisibility);
}
} // namespace
EditPeerHistoryVisibilityBox::EditPeerHistoryVisibilityBox(
QWidget*,
not_null<PeerData*> peer,
FnMut<void(HistoryVisibility)> savedCallback,
HistoryVisibility historyVisibilitySavedValue)
: _peer(peer)
, _savedCallback(std::move(savedCallback))
, _historyVisibilitySavedValue(historyVisibilitySavedValue)
, _historyVisibility(
std::make_shared<Ui::RadioenumGroup<HistoryVisibility>>(
_historyVisibilitySavedValue)) {
}
void EditPeerHistoryVisibilityBox::prepare() {
_peer->updateFull();
setTitle(tr::lng_manage_history_visibility_title());
addButton(tr::lng_settings_save(), [=] {
auto local = std::move(_savedCallback);
local(_historyVisibility->value());
closeBox();
});
addButton(tr::lng_cancel(), [=] { closeBox(); });
setupContent();
}
void EditPeerHistoryVisibilityBox::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
FillContent(
content,
_peer,
_historyVisibility,
_historyVisibilitySavedValue);
setDimensionsToContent(st::boxWidth, content);
st::defaultBoxCheckbox));
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
(isLegacy
? tr::lng_manage_history_visibility_hidden_legacy
: tr::lng_manage_history_visibility_hidden_about)(),
st::editPeerPrivacyLabel),
st::editPeerPreHistoryLabelMargins + st::boxRowPadding);
}

View File

@@ -7,32 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/widgets/checkbox.h"
namespace Ui {
class GenericBox;
} // namespace Ui
enum class HistoryVisibility {
Visible,
Hidden,
};
class EditPeerHistoryVisibilityBox : public Ui::BoxContent {
public:
EditPeerHistoryVisibilityBox(
QWidget*,
not_null<PeerData*> peer,
FnMut<void(HistoryVisibility)> savedCallback,
HistoryVisibility historyVisibilitySavedValue);
protected:
void prepare() override;
private:
void setupContent();
not_null<PeerData*> _peer;
FnMut<void(HistoryVisibility)> _savedCallback;
HistoryVisibility _historyVisibilitySavedValue;
std::shared_ptr<Ui::RadioenumGroup<HistoryVisibility>> _historyVisibility;
};
void EditPeerHistoryVisibilityBox(
not_null<Ui::GenericBox*> box,
bool isLegacy,
Fn<void(HistoryVisibility)> savedCallback,
HistoryVisibility historyVisibilitySavedValue);

View File

@@ -37,9 +37,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/admin_log/history_admin_log_section.h"
#include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "mtproto/sender.h"
#include "settings/settings_common.h"
#include "ui/rp_widget.h"
#include "ui/special_buttons.h"
#include "ui/toast/toast.h"
@@ -53,22 +52,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h"
#include "info/profile/info_profile_icon.h"
#include "apiwrap.h"
#include "api/api_invite_links.h"
#include "facades.h"
#include "facades.h" // Ui::showChatsList
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
#include "styles/style_settings.h"
namespace {
auto ToPositiveNumberString() {
[[nodiscard]] auto ToPositiveNumberString() {
return rpl::map([](int count) {
return count ? QString::number(count) : QString();
});
}
auto ToPositiveNumberStringRestrictions() {
[[nodiscard]] auto ToPositiveNumberStringRestrictions() {
return rpl::map([](int count) {
return QString::number(count)
+ QString("/")
@@ -94,40 +93,29 @@ void AddButtonWithCount(
rpl::producer<QString> &&text,
rpl::producer<QString> &&count,
Fn<void()> callback,
const style::icon &icon) {
Settings::IconDescriptor &&descriptor) {
parent->add(EditPeerInfoBox::CreateButton(
parent,
std::move(text),
std::move(count),
std::move(callback),
st::manageGroupButton,
&icon));
std::move(descriptor)));
}
object_ptr<Ui::SettingsButton> CreateButtonWithText(
not_null<QWidget*> parent,
not_null<Ui::SettingsButton*> AddButtonWithText(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
rpl::producer<QString> &&label,
Fn<void()> callback) {
return EditPeerInfoBox::CreateButton(
Fn<void()> callback,
Settings::IconDescriptor &&descriptor) {
return parent->add(EditPeerInfoBox::CreateButton(
parent,
std::move(text),
std::move(label),
std::move(callback),
st::manageGroupTopButtonWithText,
nullptr);
}
Ui::SettingsButton *AddButtonWithText(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
rpl::producer<QString> &&label,
Fn<void()> callback) {
return parent->add(CreateButtonWithText(
parent,
std::move(text),
std::move(label),
std::move(callback)));
std::move(descriptor)));
}
void AddButtonDelete(
@@ -140,7 +128,7 @@ void AddButtonDelete(
rpl::single(QString()),
std::move(callback),
st::manageDeleteGroupButton,
nullptr));
{}));
}
void SaveDefaultRestrictions(
@@ -262,7 +250,7 @@ public:
not_null<Ui::BoxContent*> box,
not_null<PeerData*> peer);
object_ptr<Ui::VerticalLayout> createContent();
[[nodiscard]] object_ptr<Ui::VerticalLayout> createContent();
void setFocus();
private:
@@ -284,12 +272,12 @@ private:
std::optional<ChannelData*> linkedChat;
};
object_ptr<Ui::RpWidget> createPhotoAndTitleEdit();
object_ptr<Ui::RpWidget> createTitleEdit();
object_ptr<Ui::RpWidget> createPhotoEdit();
object_ptr<Ui::RpWidget> createDescriptionEdit();
object_ptr<Ui::RpWidget> createManageGroupButtons();
object_ptr<Ui::RpWidget> createStickersEdit();
[[nodiscard]] object_ptr<Ui::RpWidget> createPhotoAndTitleEdit();
[[nodiscard]] object_ptr<Ui::RpWidget> createTitleEdit();
[[nodiscard]] object_ptr<Ui::RpWidget> createPhotoEdit();
[[nodiscard]] object_ptr<Ui::RpWidget> createDescriptionEdit();
[[nodiscard]] object_ptr<Ui::RpWidget> createManageGroupButtons();
[[nodiscard]] object_ptr<Ui::RpWidget> createStickersEdit();
[[nodiscard]] bool canEditInformation() const;
[[nodiscard]] bool canEditReactions() const;
@@ -310,14 +298,14 @@ private:
void deleteWithConfirmation();
void deleteChannel();
std::optional<Saving> validate() const;
bool validateUsername(Saving &to) const;
bool validateLinkedChat(Saving &to) const;
bool validateTitle(Saving &to) const;
bool validateDescription(Saving &to) const;
bool validateHistoryVisibility(Saving &to) const;
bool validateSignatures(Saving &to) const;
bool validateForwards(Saving &to) const;
[[nodiscard]] std::optional<Saving> validate() const;
[[nodiscard]] bool validateUsername(Saving &to) const;
[[nodiscard]] bool validateLinkedChat(Saving &to) const;
[[nodiscard]] bool validateTitle(Saving &to) const;
[[nodiscard]] bool validateDescription(Saving &to) const;
[[nodiscard]] bool validateHistoryVisibility(Saving &to) const;
[[nodiscard]] bool validateSignatures(Saving &to) const;
[[nodiscard]] bool validateForwards(Saving &to) const;
void save();
void saveUsername();
@@ -522,7 +510,8 @@ object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
result->entity()->setInstantReplaces(Ui::InstantReplaces::Default());
result->entity()->setInstantReplacesEnabled(
Core::App().settings().replaceEmojiValue());
result->entity()->setSubmitSettings(Core::App().settings().sendSubmitWay());
result->entity()->setSubmitSettings(
Core::App().settings().sendSubmitWay());
Ui::Emoji::SuggestionsController::Init(
_wrap->window(),
result->entity(),
@@ -739,7 +728,8 @@ void Controller::fillPrivacyTypeButton() {
? tr::lng_manage_private_group_title
: tr::lng_manage_private_peer_title)();
}) | rpl::flatten_latest(),
[=] { showEditPeerTypeBox(); });
[=] { showEditPeerTypeBox(); },
{ &st::infoIconGroupType, Settings::kIconLightBlue });
_privacyTypeUpdates.fire_copy(*_privacySavedValue);
}
@@ -781,7 +771,8 @@ void Controller::fillLinkedChatButton() {
_controls.buttonsLayout,
std::move(text),
std::move(label),
[=] { showEditLinkedChatBox(); });
[=] { showEditLinkedChatBox(); },
{ &st::settingsIconChat, Settings::kIconGreen });
_linkedChatUpdates.fire_copy(*_linkedChatSavedValue);
}
//
@@ -803,13 +794,16 @@ void Controller::fillSignaturesButton() {
Expects(_controls.buttonsLayout != nullptr);
const auto channel = _peer->asChannel();
if (!channel) return;
if (!channel) {
return;
}
AddButtonWithText(
_controls.buttonsLayout,
tr::lng_edit_sign_messages(),
rpl::single(QString()),
[=] {}
[] {},
{ &st::infoIconSignature, Settings::kIconLightBlue }
)->toggleOn(rpl::single(channel->addsSignature())
)->toggledValue(
) | rpl::start_with_next([=](bool toggled) {
@@ -843,12 +837,23 @@ void Controller::fillHistoryVisibilityButton() {
_historyVisibilitySavedValue = checked;
});
const auto buttonCallback = [=] {
_navigation->parentController()->show(
Box<EditPeerHistoryVisibilityBox>(
_peer,
boxCallback,
*_historyVisibilitySavedValue),
Ui::LayerOption::KeepOther);
_peer->updateFull();
const auto canEdit = [&] {
if (const auto chat = _peer->asChat()) {
return chat->canEditPreHistoryHidden();
} else if (const auto channel = _peer->asChannel()) {
return channel->canEditPreHistoryHidden();
}
Unexpected("User in HistoryVisibilityEdit.");
}();
if (!canEdit) {
return;
}
_navigation->parentController()->show(Box(
EditPeerHistoryVisibilityBox,
_peer->isChat(),
boxCallback,
*_historyVisibilitySavedValue));
};
AddButtonWithText(
container,
@@ -859,7 +864,8 @@ void Controller::fillHistoryVisibilityButton() {
? tr::lng_manage_history_visibility_shown
: tr::lng_manage_history_visibility_hidden)();
}) | rpl::flatten_latest(),
buttonCallback);
buttonCallback,
{ &st::settingsIconChat, Settings::kIconGreen });
updateHistoryVisibility->fire_copy(*_historyVisibilitySavedValue);
@@ -970,6 +976,40 @@ void Controller::fillManageSection() {
st::editPeerTopButtonsLayoutSkipCustomBottom);
}
if (canEditReactions()) {
const auto session = &_peer->session();
auto reactionsCount = Info::Profile::MigratedOrMeValue(
_peer
) | rpl::map(
Info::Profile::AllowedReactionsCountValue
) | rpl::flatten_latest();
auto fullCount = Info::Profile::FullReactionsCountValue(session);
auto label = rpl::combine(
std::move(reactionsCount),
std::move(fullCount)
) | rpl::map([=](int allowed, int total) {
return allowed
? QString::number(allowed) + " / " + QString::number(total)
: tr::lng_manage_peer_reactions_off(tr::now);
});
const auto done = [=](const std::vector<QString> &chosen) {
SaveAllowedReactions(_peer, chosen);
};
AddButtonWithCount(
_controls.buttonsLayout,
tr::lng_manage_peer_reactions(),
std::move(label),
[=] {
_navigation->parentController()->show(Box(
EditAllowedReactionsBox,
!_peer->isBroadcast(),
session->data().reactions().list(
Data::Reactions::Type::Active),
*Data::PeerAllowedReactions(_peer),
done));
},
{ &st::infoIconReactions, Settings::kIconRed });
}
if (canEditPermissions) {
AddButtonWithCount(
_controls.buttonsLayout,
@@ -981,7 +1021,7 @@ void Controller::fillManageSection() {
) | rpl::flatten_latest(
) | ToPositiveNumberStringRestrictions(),
[=] { ShowEditPermissions(_navigation, _peer); },
st::infoIconPermissions);
{ &st::settingsIconKey, Settings::kIconGreen });
}
if (canEditInviteLinks) {
auto count = Info::Profile::MigratedOrMeValue(
@@ -1017,7 +1057,7 @@ void Controller::fillManageSection() {
0),
Ui::LayerOption::KeepOther);
},
st::infoIconInviteLinks);
{ &st::infoIconInviteLinks, Settings::kIconLightOrange });
if (_privacySavedValue) {
_privacyTypeUpdates.events_starting_with_copy(
@@ -1029,40 +1069,6 @@ void Controller::fillManageSection() {
}, wrap->lifetime());
}
}
if (canEditReactions()) {
const auto session = &_peer->session();
auto reactionsCount = Info::Profile::MigratedOrMeValue(
_peer
) | rpl::map(
Info::Profile::AllowedReactionsCountValue
) | rpl::flatten_latest();
auto fullCount = Info::Profile::FullReactionsCountValue(session);
auto label = rpl::combine(
std::move(reactionsCount),
std::move(fullCount)
) | rpl::map([=](int allowed, int total) {
return allowed
? QString::number(allowed) + " / " + QString::number(total)
: tr::lng_manage_peer_reactions_off(tr::now);
});
const auto done = [=](const std::vector<QString> &chosen) {
SaveAllowedReactions(_peer, chosen);
};
AddButtonWithCount(
_controls.buttonsLayout,
tr::lng_manage_peer_reactions(),
std::move(label),
[=] {
_navigation->parentController()->show(Box(
EditAllowedReactionsBox,
!_peer->isBroadcast(),
session->data().reactions().list(
Data::Reactions::Type::Active),
*Data::PeerAllowedReactions(_peer),
done));
},
st::infoIconReactions);
}
if (canViewAdmins) {
AddButtonWithCount(
_controls.buttonsLayout,
@@ -1079,12 +1085,14 @@ void Controller::fillManageSection() {
_peer,
ParticipantsBoxController::Role::Admins);
},
st::infoIconAdministrators);
{ &st::infoIconAdministrators, Settings::kIconLightBlue });
}
if (canViewMembers) {
AddButtonWithCount(
_controls.buttonsLayout,
(_isGroup ? tr::lng_manage_peer_members() : tr::lng_manage_peer_subscribers()),
(_isGroup
? tr::lng_manage_peer_members()
: tr::lng_manage_peer_subscribers()),
Info::Profile::MigratedOrMeValue(
_peer
) | rpl::map(
@@ -1097,7 +1105,7 @@ void Controller::fillManageSection() {
_peer,
ParticipantsBoxController::Role::Members);
},
st::infoIconMembers);
{ &st::settingsIconGroup, Settings::kIconDarkBlue });
}
fillPendingRequestsButton();
@@ -1114,7 +1122,7 @@ void Controller::fillManageSection() {
_peer,
ParticipantsBoxController::Role::Kicked);
},
st::infoIconBlacklist);
{ &st::settingsIconMinus, Settings::kIconRed });
}
if (hasRecentActions) {
auto callback = [=] {
@@ -1126,7 +1134,7 @@ void Controller::fillManageSection() {
tr::lng_manage_peer_recent_actions(),
rpl::single(QString()), //Empty count.
std::move(callback),
st::infoIconRecentActions);
{ &st::infoIconRecentActions, Settings::kIconPurple });
}
if (canEditStickers || canDeleteChannel) {
@@ -1168,7 +1176,7 @@ void Controller::fillPendingRequestsButton() {
: tr::lng_manage_peer_requests_channel()),
rpl::duplicate(pendingRequestsCount) | ToPositiveNumberString(),
[=] { RequestsBoxController::Start(_navigation, _peer); },
st::infoIconRequests);
{ &st::infoIconRequests, Settings::kIconRed });
std::move(
pendingRequestsCount
) | rpl::start_with_next([=](int count) {
@@ -1670,18 +1678,18 @@ object_ptr<Ui::SettingsButton> EditPeerInfoBox::CreateButton(
rpl::producer<QString> &&count,
Fn<void()> callback,
const style::SettingsCountButton &st,
const style::icon *icon) {
Settings::IconDescriptor &&descriptor) {
auto result = object_ptr<Ui::SettingsButton>(
parent,
rpl::duplicate(text),
st.button);
const auto button = result.data();
button->addClickHandler(callback);
if (icon) {
Ui::CreateChild<Info::Profile::FloatingIcon>(
if (descriptor) {
AddButtonIcon(
button,
*icon,
st.iconPosition);
st.button,
std::move(descriptor));
}
auto labelText = rpl::combine(

View File

@@ -7,8 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include <rpl/event_stream.h>
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
namespace Settings {
struct IconDescriptor;
} // namespace Settings
namespace style {
struct SettingsCountButton;
@@ -42,7 +45,7 @@ public:
rpl::producer<QString> &&count,
Fn<void()> callback,
const style::SettingsCountButton &st,
const style::icon *icon = nullptr);
Settings::IconDescriptor &&descriptor);
protected:
void prepare() override;

View File

@@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "mainwindow.h"
#include "apiwrap.h"
#include "settings/settings_common.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
@@ -612,7 +613,8 @@ void EditPeerPermissionsBox::addSuggestGigagroup(
AboutGigagroupCallback(
_peer->asChannel(),
_navigation->parentController()),
st::peerPermissionsButton));
st::peerPermissionsButton,
{}));
container->add(
object_ptr<Ui::DividerLabel>(
@@ -645,7 +647,8 @@ void EditPeerPermissionsBox::addBannedButtons(
_peer,
ParticipantsBoxController::Role::Restricted);
},
st::peerPermissionsButton));
st::peerPermissionsButton,
{}));
if (channel) {
container->add(EditPeerInfoBox::CreateButton(
container,
@@ -658,7 +661,8 @@ void EditPeerPermissionsBox::addBannedButtons(
_peer,
ParticipantsBoxController::Role::Kicked);
},
st::peerPermissionsButton));
st::peerPermissionsButton,
{}));
}
}

View File

@@ -7,92 +7,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/edit_peer_reactions.h"
#include "boxes/reactions_settings_box.h" // AddReactionLottieIcon
#include "data/data_message_reactions.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_peer.h"
#include "data/data_chat.h"
#include "data/data_channel.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "lottie/lottie_icon.h"
#include "lang/lang_keys.h"
#include "ui/layers/generic_box.h"
#include "ui/widgets/buttons.h"
#include "info/profile/info_profile_icon.h"
#include "settings/settings_common.h"
#include "styles/style_settings.h"
#include "styles/style_info.h"
namespace {
using Data::Reaction;
void AddReactionIcon(
not_null<Ui::RpWidget*> button,
not_null<DocumentData*> document) {
struct State {
std::shared_ptr<Data::DocumentMedia> media;
std::unique_ptr<Lottie::Icon> icon;
QImage image;
};
const auto size = st::editPeerReactionsPreview;
const auto state = button->lifetime().make_state<State>(State{
.media = document->createMediaView(),
});
const auto icon = Ui::CreateChild<Ui::RpWidget>(button.get());
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
icon->resize(size, size);
button->sizeValue(
) | rpl::start_with_next([=](QSize size) {
icon->moveToLeft(
st::editPeerReactionsIconLeft,
(size.height() - icon->height()) / 2,
size.width());
}, icon->lifetime());
const auto initLottie = [=] {
state->icon = Lottie::MakeIcon({
.path = state->media->owner()->filepath(true),
.json = state->media->bytes(),
.sizeOverride = QSize(size, size),
.frame = -1,
});
state->media = nullptr;
};
state->media->checkStickerLarge();
if (state->media->loaded()) {
initLottie();
} else {
document->session().downloaderTaskFinished(
) | rpl::filter([=] {
return state->media->loaded();
}) | rpl::take(1) | rpl::start_with_next([=] {
initLottie();
icon->update();
}, icon->lifetime());
}
icon->paintRequest(
) | rpl::start_with_next([=] {
QPainter p(icon);
if (state->image.isNull() && state->icon) {
state->image = state->icon->frame();
crl::async([icon = std::move(state->icon)]{});
}
if (!state->image.isNull()) {
p.drawImage(QRect(0, 0, size, size), state->image);
}
}, icon->lifetime());
}
} // namespace
void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box,
bool isGroup,
const std::vector<Reaction> &list,
const std::vector<Data::Reaction> &list,
const base::flat_set<QString> &selected,
Fn<void(const std::vector<QString> &)> callback) {
box->setTitle(tr::lng_manage_peer_reactions());
@@ -153,9 +87,23 @@ void EditAllowedReactionsBox(
container,
rpl::single(entry.title),
st::manageGroupButton.button);
AddReactionIcon(button, entry.centerIcon
? entry.centerIcon
: entry.appearAnimation.get());
const auto iconHeight = st::editPeerReactionsPreview;
AddReactionLottieIcon(
button,
button->sizeValue(
) | rpl::map([=](const QSize &size) {
return QPoint(
st::editPeerReactionsIconLeft,
(size.height() - iconHeight) / 2);
}),
iconHeight,
entry,
button->events(
) | rpl::filter([=](not_null<QEvent*> event) {
return event->type() == QEvent::Enter;
}) | rpl::to_empty,
rpl::never<>(),
&button->lifetime());
state->toggles.emplace(entry.emoji, button);
button->toggleOn(rpl::single(
active(entry)

View File

@@ -7,14 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "ui/layers/generic_box.h"
class PeerData;
namespace Data {
struct Reaction;
} // namespace Data
namespace Ui {
class GenericBox;
} // namespace Ui
void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box,
bool isGroup,

View File

@@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/edit_peer_type_box.h"
#include "apiwrap.h"
#include "api/api_invite_links.h"
#include "main/main_session.h"
#include "boxes/add_contact_box.h"
#include "ui/boxes/confirm_box.h"
@@ -19,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_invite_link.h"
#include "boxes/peers/edit_peer_invite_links.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "core/application.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_peer.h"
@@ -27,7 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h"
#include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "mtproto/sender.h"
#include "ui/rp_widget.h"
#include "ui/special_buttons.h"
@@ -35,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/checkbox.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/box_content_divider.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
@@ -48,11 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_info.h"
#include "styles/style_settings.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
#include <rpl/flatten_latest.h>
namespace {
class Controller : public base::has_weak_ptr {
@@ -209,21 +199,22 @@ void Controller::createContent() {
Ui::LayerOption::KeepOther);
},
st::manageGroupButton,
&st::infoIconInviteLinks));
{ &st::infoIconInviteLinks, Settings::kIconLightOrange }));
AddSkip(_wrap.get());
AddDividerText(_wrap.get(), tr::lng_group_invite_manage_about());
if (!_linkOnly) {
AddSkip(_wrap.get());
AddSubsectionTitle(_wrap.get(), tr::lng_manage_peer_no_forwards_title());
AddSubsectionTitle(
_wrap.get(),
tr::lng_manage_peer_no_forwards_title());
_controls.noForwards = _wrap->add(EditPeerInfoBox::CreateButton(
_wrap.get(),
tr::lng_manage_peer_no_forwards(),
rpl::single(QString()),
[=] {},
st::manageGroupTopButtonWithText,
nullptr
));
[] {},
st::peerPermissionsButton,
{}));
_controls.noForwards->toggleOn(
rpl::single(_noForwardsSavedValue.value_or(false))
)->toggledValue(

View File

@@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "base/timer.h"
#include "ui/layers/box_content.h"
namespace style {
struct SettingsCountButton;

View File

@@ -234,7 +234,6 @@ void AddMessage(
(rightSize.height() - iconSize) / 2);
}),
iconSize,
&controller->session(),
r,
rpl::never<>(),
rpl::duplicate(emojiValue) | rpl::skip(1) | rpl::to_empty,
@@ -251,7 +250,6 @@ void AddReactionLottieIcon(
not_null<Ui::RpWidget*> parent,
rpl::producer<QPoint> iconPositionValue,
int iconSize,
not_null<Main::Session*> session,
const Data::Reaction &reaction,
rpl::producer<> &&selects,
rpl::producer<> &&destroys,
@@ -280,7 +278,7 @@ void AddReactionLottieIcon(
state->appear.media->checkStickerLarge();
state->select.media->checkStickerLarge();
rpl::single() | rpl::then(
session->downloaderTaskFinished()
reaction.appearAnimation->session().downloaderTaskFinished()
) | rpl::start_with_next([=] {
const auto check = [&](State::Entry &entry) {
if (!entry.media) {
@@ -448,7 +446,6 @@ void ReactionsSettingsBox(
(s.height() - iconSize) / 2);
}),
iconSize,
&controller->session(),
r,
button->events(
) | rpl::filter([=](not_null<QEvent*> event) {

View File

@@ -16,10 +16,6 @@ namespace Window {
class SessionController;
} // namespace Window
namespace Main {
class Session;
} // namespace Main
namespace Data {
struct Reaction;
} // namespace Data
@@ -28,7 +24,6 @@ void AddReactionLottieIcon(
not_null<Ui::RpWidget*> parent,
rpl::producer<QPoint> iconPositionValue,
int iconSize,
not_null<Main::Session*> session,
const Data::Reaction &reaction,
rpl::producer<> &&selects,
rpl::producer<> &&destroys,

View File

@@ -0,0 +1,106 @@
/*
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/report_messages_box.h"
#include "api/api_report.h"
#include "data/data_peer.h"
#include "data/data_photo.h"
#include "lang/lang_keys.h"
#include "ui/boxes/report_box.h"
#include "ui/layers/generic_box.h"
#include "window/window_session_controller.h"
namespace {
[[nodiscard]] object_ptr<Ui::BoxContent> Report(
not_null<PeerData*> peer,
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data) {
const auto source = v::match(data, [](const MessageIdsList &ids) {
return Ui::ReportSource::Message;
}, [](not_null<PhotoData*> photo) {
return photo->hasVideo()
? Ui::ReportSource::ProfileVideo
: Ui::ReportSource::ProfilePhoto;
}, [](v::null_t) {
Unexpected("Bad source report.");
return Ui::ReportSource::Bot;
});
return Box([=](not_null<Ui::GenericBox*> box) {
Ui::ReportReasonBox(box, source, [=](Ui::ReportReason reason) {
Ui::BoxShow(box).showBox(Box([=](not_null<Ui::GenericBox*> box) {
const auto show = Ui::BoxShow(box);
Ui::ReportDetailsBox(box, [=](const QString &text) {
const auto toastParent = show.toastParent();
Api::SendReport(toastParent, peer, reason, text, data);
show.hideLayer();
});
}));
});
});
}
} // namespace
object_ptr<Ui::BoxContent> ReportItemsBox(
not_null<PeerData*> peer,
MessageIdsList ids) {
return Report(peer, ids);
}
object_ptr<Ui::BoxContent> ReportProfilePhotoBox(
not_null<PeerData*> peer,
not_null<PhotoData*> photo) {
return Report(peer, photo);
}
void ShowReportPeerBox(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer) {
struct State {
QPointer<Ui::BoxContent> reasonBox;
QPointer<Ui::BoxContent> detailsBox;
MessageIdsList ids;
};
const auto state = std::make_shared<State>();
const auto chosen = [=](Ui::ReportReason reason) {
const auto send = [=](const QString &text) {
window->clearChooseReportMessages();
Api::SendReport(
Window::Show(window).toastParent(),
peer,
reason,
text,
std::move(state->ids));
if (const auto strong = state->reasonBox.data()) {
strong->closeBox();
}
if (const auto strong = state->detailsBox.data()) {
strong->closeBox();
}
};
if (reason == Ui::ReportReason::Fake
|| reason == Ui::ReportReason::Other) {
state->ids = {};
state->detailsBox = window->show(Box(Ui::ReportDetailsBox, send));
return;
}
window->showChooseReportMessages(peer, reason, [=](
MessageIdsList ids) {
state->ids = std::move(ids);
state->detailsBox = window->show(Box(Ui::ReportDetailsBox, send));
});
};
state->reasonBox = window->show(Box(
Ui::ReportReasonBox,
(peer->isBroadcast()
? Ui::ReportSource::Channel
: peer->isUser()
? Ui::ReportSource::Bot
: Ui::ReportSource::Group),
chosen));
}

View File

@@ -0,0 +1,31 @@
/*
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
template <typename Object>
class object_ptr;
namespace Ui {
class BoxContent;
} // namespace Ui
namespace Window {
class SessionController;
} // namespace Main
class PeerData;
[[nodiscard]] object_ptr<Ui::BoxContent> ReportItemsBox(
not_null<PeerData*> peer,
MessageIdsList ids);
[[nodiscard]] object_ptr<Ui::BoxContent> ReportProfilePhotoBox(
not_null<PeerData*> peer,
not_null<PhotoData*> photo);
void ShowReportPeerBox(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer);

View File

@@ -1065,6 +1065,7 @@ void GroupCall::start(TimeId scheduleDate, bool rtmp) {
MTPstring(), // title
MTP_int(scheduleDate)
)).done([=](const MTPUpdates &result) {
_reloadedStaleCall = true;
_acceptFields = true;
_peer->session().api().applyUpdates(result);
_acceptFields = false;
@@ -1393,6 +1394,13 @@ void GroupCall::rejoin(not_null<PeerData*> as) {
sendSelfUpdate(SendUpdateType::CameraPaused);
}
sendPendingSelfUpdates();
if (!_reloadedStaleCall
&& _state.current() != State::Joining) {
if (const auto real = lookupReal()) {
_reloadedStaleCall = true;
real->reloadIfStale();
}
}
}).fail([=](const MTP::Error &error) {
_joinState.finish();

View File

@@ -674,6 +674,7 @@ private:
bool _hadJoinedState = false;
bool _listenersHidden = false;
bool _rtmp = false;
bool _reloadedStaleCall = false;
int _rtmpVolume = 0;
std::unique_ptr<Webrtc::MediaDevices> _mediaDevices;

View File

@@ -239,8 +239,9 @@ QByteArray Settings::serialize() const {
}
stream
<< qint32(_hardwareAcceleratedVideo ? 1 : 0)
<< qint32(_chatQuickAction);
<< qint32(0) // old hardwareAcceleratedVideo
<< qint32(_chatQuickAction)
<< qint32(_hardwareAcceleratedVideo ? 1 : 0);
}
return result;
}
@@ -514,11 +515,15 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
}
}
if (!stream.atEnd()) {
stream >> hardwareAcceleratedVideo;
qint32 legacyHardwareAcceleratedVideo = 0;
stream >> legacyHardwareAcceleratedVideo;
}
if (!stream.atEnd()) {
stream >> chatQuickAction;
}
if (!stream.atEnd()) {
stream >> hardwareAcceleratedVideo;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));

View File

@@ -792,7 +792,11 @@ private:
rpl::variable<Media::Player::OrderMode> _playerOrderMode;
bool _macWarnBeforeQuit = true;
std::vector<uint64> _accountsOrder;
#ifdef Q_OS_MAC
bool _hardwareAcceleratedVideo = true;
#else // Q_OS_MAC
bool _hardwareAcceleratedVideo = false;
#endif // Q_OS_MAC
HistoryView::DoubleClickQuickAction _chatQuickAction =
HistoryView::DoubleClickQuickAction();

View File

@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QDesktopServices>
#include <QtCore/QStandardPaths>
#include <QtCore/QTimer>
#include <qpa/qplatformscreen.h>
namespace {
@@ -43,7 +44,18 @@ PreLaunchWindow::PreLaunchWindow(QString title) {
p.setColor(QPalette::Window, QColor(255, 255, 255));
setPalette(p);
_size = QFontMetrics(QGuiApplication::font()).height();
constexpr auto processDpi = [](const QDpi &dpi) {
return (dpi.first + dpi.second) * 0.5;
};
const auto screen = QGuiApplication::primaryScreen();
const auto scale = processDpi(screen->handle()->logicalDpi())
/ processDpi(screen->handle()->logicalBaseDpi());
auto font = QGuiApplication::font();
font.setPixelSize(base::SafeRound(font.pointSize() * scale));
_size = QFontMetrics(font).height();
int paddingVertical = (_size / 2);
int paddingHorizontal = _size;

View File

@@ -219,8 +219,8 @@ void Sandbox::launchApplication() {
}
void Sandbox::setupScreenScale() {
const auto processDpi = [](const QDpi &dpi) {
return (dpi.first + dpi.second) * qreal(0.5);
constexpr auto processDpi = [](const QDpi &dpi) {
return (dpi.first + dpi.second) * 0.5;
};
const auto dpi = processDpi(
Sandbox::primaryScreen()->handle()->logicalDpi());

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 3007000;
constexpr auto AppVersionStr = "3.7";
constexpr auto AppVersion = 3007002;
constexpr auto AppVersionStr = "3.7.2";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -208,4 +208,8 @@ UpdatedFileReferences GetFileReferences(
return GetFileReferencesHelper(data);
}
UpdatedFileReferences GetFileReferences(const MTPMessageMedia &data) {
return GetFileReferencesHelper(data);
}
} // namespace Data

View File

@@ -179,4 +179,7 @@ UpdatedFileReferences GetFileReferences(const MTPTheme &data);
UpdatedFileReferences GetFileReferences(
const MTPaccount_SavedRingtones &data);
// Admin Log Event.
UpdatedFileReferences GetFileReferences(const MTPMessageMedia &data);
} // namespace Data

View File

@@ -26,6 +26,7 @@ constexpr auto kRequestPerPage = 50;
constexpr auto kSpeakingAfterActive = crl::time(6000);
constexpr auto kActiveAfterJoined = crl::time(1000);
constexpr auto kWaitForUpdatesTimeout = 3 * crl::time(1000);
constexpr auto kReloadStaleTimeout = 16 * crl::time(1000);
[[nodiscard]] QString ExtractNextOffset(const MTPphone_GroupCall &call) {
return call.match([&](const MTPDphone_groupCall &data) {
@@ -168,6 +169,7 @@ bool GroupCall::processSavedFullCall() {
return false;
}
_reloadRequestId = 0;
_reloadLastFinished = crl::now();
processFullCallFields(*base::take(_savedFull));
return true;
}
@@ -497,6 +499,15 @@ void GroupCall::computeParticipantsCount() {
: std::max(int(_participants.size()), _serverParticipantsCount);
}
void GroupCall::reloadIfStale() {
if (!fullCount() && !participantsLoaded()) {
reload();
} else if (!_reloadLastFinished
|| crl::now() > _reloadLastFinished + kReloadStaleTimeout) {
reload();
}
}
void GroupCall::reload() {
if (_reloadRequestId || _applyingQueuedUpdates) {
return;
@@ -528,9 +539,11 @@ void GroupCall::reload() {
return;
}
_reloadRequestId = 0;
_reloadLastFinished = crl::now();
processFullCall(result);
}).fail([=] {
_reloadRequestId = 0;
_reloadLastFinished = crl::now();
}).send();
}

View File

@@ -156,6 +156,7 @@ public:
void setInCall();
void reload();
void reloadIfStale();
void processFullCall(const MTPphone_GroupCall &call);
void setJoinMutedLocally(bool muted);
@@ -206,6 +207,7 @@ private:
int _version = 0;
mtpRequestId _participantsRequestId = 0;
mtpRequestId _reloadRequestId = 0;
crl::time _reloadLastFinished = 0;
rpl::variable<QString> _title;
base::flat_multi_map<

View File

@@ -86,6 +86,8 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
}
[[nodiscard]] bool InitHw(AVCodecContext *context, AVHWDeviceType type) {
AVCodecContext *parent = static_cast<AVCodecContext*>(context->opaque);
auto hwDeviceContext = (AVBufferRef*)nullptr;
AvErrorWrap error = av_hwdevice_ctx_create(
&hwDeviceContext,
@@ -101,11 +103,13 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
"Trying \"%1\" hardware acceleration for \"%2\" decoder."
).arg(av_hwdevice_get_type_name(type)
).arg(context->codec->name));
if (context->hw_device_ctx) {
av_buffer_unref(&context->hw_device_ctx);
if (parent->hw_device_ctx) {
av_buffer_unref(&parent->hw_device_ctx);
}
context->hw_device_ctx = av_buffer_ref(hwDeviceContext);
parent->hw_device_ctx = av_buffer_ref(hwDeviceContext);
av_buffer_unref(&hwDeviceContext);
context->hw_device_ctx = parent->hw_device_ctx;
return true;
}
@@ -294,6 +298,7 @@ CodecPointer MakeCodecPointer(CodecDescriptor descriptor) {
if (descriptor.hwAllowed) {
context->get_format = GetHwFormat;
context->opaque = context;
} else {
DEBUG_LOG(("Video Info: Using software \"%2\" decoder."
).arg(codec->name));

View File

@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_chat_participants.h"
#include "api/api_text_entities.h"
#include "data/data_channel.h"
#include "data/data_file_origin.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "lang/lang_keys.h"
@@ -136,6 +137,18 @@ bool MediaCanHaveCaption(const MTPMessage &message) {
|| (mediaType == mtpc_messageMediaPhoto);
}
uint64 MediaId(const MTPMessage &message) {
if (!MediaCanHaveCaption(message)) {
return 0;
}
const auto &media = message.c_message().vmedia();
return media
? v::match(
Data::GetFileReferences(*media).data.begin()->first,
[](const auto &d) { return d.id; })
: 0;
}
TextWithEntities ExtractEditedText(
not_null<Main::Session*> session,
const MTPMessage &message) {
@@ -868,22 +881,36 @@ void GenerateItems(
const auto newValue = ExtractEditedText(
session,
action.vnew_message());
auto oldValue = ExtractEditedText(
session,
action.vprev_message());
const auto canHaveCaption = MediaCanHaveCaption(
action.vnew_message());
const auto changedCaption = (newValue != oldValue);
const auto changedMedia = MediaId(action.vnew_message())
!= MediaId(action.vprev_message());
const auto removedCaption = !oldValue.text.isEmpty()
&& newValue.text.isEmpty();
const auto text = (!canHaveCaption
? tr::lng_admin_log_edited_message
: newValue.text.isEmpty()
: (changedMedia && removedCaption)
? tr::lng_admin_log_edited_media_and_removed_caption
: (changedMedia && changedCaption)
? tr::lng_admin_log_edited_media_and_caption
: changedMedia
? tr::lng_admin_log_edited_media
: removedCaption
? tr::lng_admin_log_removed_caption
: tr::lng_admin_log_edited_caption)(
: changedCaption
? tr::lng_admin_log_edited_caption
: tr::lng_admin_log_edited_message)(
tr::now,
lt_from,
fromLinkText,
Ui::Text::WithEntities);
addSimpleServiceMessage(text);
auto oldValue = ExtractEditedText(
session,
action.vprev_message());
const auto detachExistingItem = false;
const auto body = history->createItem(
history->nextNonHistoryEntryId(),

View File

@@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/notifications_manager.h"
#include "boxes/about_sponsored_box.h"
#include "boxes/delete_messages_box.h"
#include "boxes/report_messages_box.h"
#include "boxes/sticker_set_box.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/emoji_interactions.h"
@@ -2247,7 +2248,8 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu,
poll,
item,
HistoryView::Context::History);
HistoryView::Context::History,
_controller);
} else if (const auto contact = media->sharedContact()) {
const auto phone = contact->phoneNumber;
_menu->addAction(tr::lng_profile_copy_phone(tr::now), [=] {
@@ -3864,17 +3866,17 @@ void HistoryInner::deleteAsGroup(FullMsgId itemId) {
}
void HistoryInner::reportItem(FullMsgId itemId) {
HistoryView::ShowReportItemsBox(_peer, { 1, itemId });
_controller->show(ReportItemsBox(_peer, { 1, itemId }));
}
void HistoryInner::reportAsGroup(FullMsgId itemId) {
if (const auto item = session().data().message(itemId)) {
const auto group = session().data().groups().find(item);
HistoryView::ShowReportItemsBox(
_controller->show(ReportItemsBox(
_peer,
(group
? session().data().itemsToIds(group->items)
: MessageIdsList{ 1, itemId }));
: MessageIdsList{ 1, itemId })));
}
}

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_editing.h"
#include "api/api_bot.h"
#include "api/api_chat_participants.h"
#include "api/api_report.h"
#include "api/api_sending.h"
#include "api/api_text_entities.h"
#include "api/api_send_progress.h"
@@ -3877,19 +3878,18 @@ void HistoryWidget::reportSelectedMessages() {
const auto ids = _list->getSelectedItems();
const auto peer = _peer;
const auto reason = _chooseForReport->reason;
const auto box = std::make_shared<QPointer<Ui::GenericBox>>();
const auto weak = Ui::MakeWeak(_list.data());
const auto send = [=](const QString &text) {
if (weak) {
clearSelected();
controller()->clearChooseReportMessages();
}
HistoryView::SendReport(peer, reason, text, ids);
if (*box) {
(*box)->closeBox();
}
};
*box = controller()->window().show(Box(Ui::ReportDetailsBox, send));
controller()->window().show(Box([=](not_null<Ui::GenericBox*> box) {
Ui::ReportDetailsBox(box, [=](const QString &text) {
if (weak) {
clearSelected();
controller()->clearChooseReportMessages();
}
const auto toastParent = Window::Show(controller()).toastParent();
Api::SendReport(toastParent, peer, reason, text, ids);
box->closeBox();
});
}));
}
History *HistoryWidget::history() const {
@@ -6388,25 +6388,28 @@ void HistoryWidget::checkPinnedBarState() {
auto barContent = HistoryView::PinnedBarContent(
&session(),
_pinnedTracker->shownMessageId());
_pinnedBar = std::make_unique<Ui::PinnedBar>(
this,
std::move(barContent));
Info::Profile::SharedMediaCountValue(
_peer,
nullptr,
Storage::SharedMediaType::Pinned
) | rpl::distinct_until_changed(
) | rpl::map([=](int count) {
if (_pinnedClickedId) {
_pinnedClickedId = FullMsgId();
_minPinnedId = std::nullopt;
updatePinnedViewer();
}
return (count > 1);
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool many) {
refreshPinnedBarButton(many);
_pinnedBar = std::make_unique<Ui::PinnedBar>(this);
rpl::combine(
Info::Profile::SharedMediaCountValue(
_peer,
nullptr,
Storage::SharedMediaType::Pinned
) | rpl::distinct_until_changed(
) | rpl::map([=](int count) {
if (_pinnedClickedId) {
_pinnedClickedId = FullMsgId();
_minPinnedId = std::nullopt;
updatePinnedViewer();
}
return (count > 1);
}) | rpl::distinct_until_changed(),
HistoryView::PinnedBarItemWithReplyMarkup(
&session(),
_pinnedTracker->shownMessageId())
) | rpl::start_with_next([=](bool many, HistoryItem *item) {
refreshPinnedBarButton(many, item);
}, _pinnedBar->lifetime());
_pinnedBar->setContent(std::move(barContent));
controller()->adaptive().oneColumnValue(
) | rpl::start_with_next([=](bool one) {
@@ -6493,7 +6496,30 @@ void HistoryWidget::setChooseReportMessagesDetails(
}
}
void HistoryWidget::refreshPinnedBarButton(bool many) {
void HistoryWidget::refreshPinnedBarButton(bool many, HistoryItem *item) {
if (const auto replyMarkup = item ? item->inlineReplyMarkup() : nullptr) {
const auto &rows = replyMarkup->data.rows;
if ((rows.size() == 1) && (rows.front().size() == 1)) {
const auto text = rows.front().front().text;
if (!text.isEmpty()) {
auto button = object_ptr<Ui::RoundButton>(
this,
rpl::single(text),
st::historyPinnedBotButton);
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->setFullRadius(true);
button->setClickedCallback([=] {
App::activateBotCommand(controller(), item, 0, 0);
});
if (button->width() > st::historyPinnedBotButtonMaxWidth) {
button->setFullWidth(st::historyPinnedBotButtonMaxWidth);
}
_pinnedBar->setRightButton(std::move(button));
return;
}
}
}
const auto close = !many;
auto button = object_ptr<Ui::IconButton>(
this,

View File

@@ -512,7 +512,7 @@ private:
void updatePinnedViewer();
void setupPinnedTracker();
void checkPinnedBarState();
void refreshPinnedBarButton(bool many);
void refreshPinnedBarButton(bool many, HistoryItem *item);
void checkLastPinnedClickedIdReset(
int wasScrollTop,
int nowScrollTop);

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_attached_stickers.h"
#include "api/api_editing.h"
#include "api/api_polls.h"
#include "api/api_report.h"
#include "api/api_ringtones.h"
#include "api/api_who_reacted.h"
#include "api/api_toggling_media.h" // Api::ToggleFavedSticker
@@ -34,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "menu/menu_send.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/delete_messages_box.h"
#include "boxes/report_messages_box.h"
#include "boxes/sticker_set_box.h"
#include "data/data_photo.h"
#include "data/data_photo_media.h"
@@ -54,11 +56,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "lang/lang_keys.h"
#include "core/application.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "apiwrap.h"
#include "facades.h"
#include "facades.h" // LambdaDelayed
#include "styles/style_chat.h"
#include "styles/style_menu_icons.h"
@@ -806,11 +807,11 @@ void AddReportAction(
const auto callback = crl::guard(controller, [=] {
if (const auto item = owner->message(itemId)) {
const auto group = owner->groups().find(item);
ShowReportItemsBox(
controller->show(ReportItemsBox(
item->history()->peer,
(group
? owner->itemsToIds(group->items)
: MessageIdsList{ 1, itemId }));
: MessageIdsList{ 1, itemId })));
}
});
menu->addAction(
@@ -960,7 +961,8 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
} else if (lnkDocument) {
AddDocumentActions(result, lnkDocument, item, list);
} else if (poll) {
AddPollActions(result, poll, item, list->elementContext());
const auto context = list->elementContext();
AddPollActions(result, poll, item, context, list->controller());
} else if (!request.overSelection && view && !hasSelection) {
const auto owner = &view->data()->history()->owner();
const auto media = view->media();
@@ -1034,26 +1036,12 @@ void CopyPostLink(
: tr::lng_context_about_private_link(tr::now));
}
void StopPoll(not_null<Main::Session*> session, FullMsgId itemId) {
const auto stop = [=] {
Ui::hideLayer();
if (const auto item = session->data().message(itemId)) {
session->api().polls().close(item);
}
};
Ui::show(Ui::MakeConfirmBox({
.text = tr::lng_polls_stop_warning(),
.confirmed = stop,
.confirmText = tr::lng_polls_stop_sure(),
.cancelText = tr::lng_cancel(),
}));
}
void AddPollActions(
not_null<Ui::PopupMenu*> menu,
not_null<PollData*> poll,
not_null<HistoryItem*> item,
Context context) {
Context context,
not_null<Window::SessionController*> controller) {
if ((context != Context::History)
&& (context != Context::Replies)
&& (context != Context::Pinned)) {
@@ -1070,7 +1058,17 @@ void AddPollActions(
}
if (item->canStopPoll()) {
menu->addAction(tr::lng_polls_stop(tr::now), [=] {
StopPoll(&poll->session(), itemId);
controller->show(Ui::MakeConfirmBox({
.text = tr::lng_polls_stop_warning(),
.confirmed = [=](Fn<void()> &&close) {
close();
if (const auto item = poll->owner().message(itemId)) {
controller->session().api().polls().close(item);
}
},
.confirmText = tr::lng_polls_stop_sure(),
.cancelText = tr::lng_cancel(),
}));
}, &st::menuIconStopPoll);
}
}
@@ -1204,108 +1202,4 @@ void ShowWhoReactedMenu(
}, lifetime);
}
void ShowReportItemsBox(not_null<PeerData*> peer, MessageIdsList ids) {
const auto chosen = [=](Ui::ReportReason reason) {
Ui::show(Box(Ui::ReportDetailsBox, [=](const QString &text) {
SendReport(peer, reason, text, ids);
Ui::hideLayer();
}));
};
Ui::show(Box(
Ui::ReportReasonBox,
Ui::ReportSource::Message,
chosen));
}
void ShowReportPeerBox(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer) {
struct State {
QPointer<Ui::GenericBox> reasonBox;
QPointer<Ui::GenericBox> detailsBox;
MessageIdsList ids;
};
const auto state = std::make_shared<State>();
const auto chosen = [=](Ui::ReportReason reason) {
const auto send = [=](const QString &text) {
window->clearChooseReportMessages();
SendReport(peer, reason, text, std::move(state->ids));
if (const auto strong = state->reasonBox.data()) {
strong->closeBox();
}
if (const auto strong = state->detailsBox.data()) {
strong->closeBox();
}
};
if (reason == Ui::ReportReason::Fake
|| reason == Ui::ReportReason::Other) {
state->ids = {};
state->detailsBox = window->window().show(
Box(Ui::ReportDetailsBox, send));
return;
}
window->showChooseReportMessages(peer, reason, [=](
MessageIdsList ids) {
state->ids = std::move(ids);
state->detailsBox = window->window().show(
Box(Ui::ReportDetailsBox, send));
});
};
state->reasonBox = window->window().show(Box(
Ui::ReportReasonBox,
(peer->isBroadcast()
? Ui::ReportSource::Channel
: peer->isUser()
? Ui::ReportSource::Bot
: Ui::ReportSource::Group),
chosen));
}
void SendReport(
not_null<PeerData*> peer,
Ui::ReportReason reason,
const QString &comment,
MessageIdsList ids) {
const auto apiReason = [&] {
using Reason = Ui::ReportReason;
switch (reason) {
case Reason::Spam: return MTP_inputReportReasonSpam();
case Reason::Fake: return MTP_inputReportReasonFake();
case Reason::Violence: return MTP_inputReportReasonViolence();
case Reason::ChildAbuse: return MTP_inputReportReasonChildAbuse();
case Reason::Pornography: return MTP_inputReportReasonPornography();
case Reason::Copyright: return MTP_inputReportReasonCopyright();
case Reason::IllegalDrugs:
return MTP_inputReportReasonIllegalDrugs();
case Reason::PersonalDetails:
return MTP_inputReportReasonPersonalDetails();
case Reason::Other: return MTP_inputReportReasonOther();
}
Unexpected("Bad reason group value.");
}();
if (ids.empty()) {
peer->session().api().request(MTPaccount_ReportPeer(
peer->input,
apiReason,
MTP_string(comment)
)).done([=] {
Ui::Toast::Show(tr::lng_report_thanks(tr::now));
}).send();
} else {
auto apiIds = QVector<MTPint>();
apiIds.reserve(ids.size());
for (const auto &fullId : ids) {
apiIds.push_back(MTP_int(fullId.msg));
}
peer->session().api().request(MTPmessages_Report(
peer->input,
MTP_vector<MTPint>(apiIds),
apiReason,
MTP_string(comment)
)).done([=] {
Ui::Toast::Show(tr::lng_report_thanks(tr::now));
}).send();
}
}
} // namespace HistoryView

View File

@@ -54,12 +54,12 @@ void CopyPostLink(
not_null<Main::Session*> session,
FullMsgId itemId,
Context context);
void StopPoll(not_null<Main::Session*> session, FullMsgId itemId);
void AddPollActions(
not_null<Ui::PopupMenu*> menu,
not_null<PollData*> poll,
not_null<HistoryItem*> item,
Context context);
Context context,
not_null<Window::SessionController*> controller);
void AddSaveSoundForNotifications(
not_null<Ui::PopupMenu*> menu,
not_null<HistoryItem*> item,
@@ -79,14 +79,4 @@ void ShowWhoReactedMenu(
not_null<Window::SessionController*> controller,
rpl::lifetime &lifetime);
void ShowReportItemsBox(not_null<PeerData*> peer, MessageIdsList ids);
void ShowReportPeerBox(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer);
void SendReport(
not_null<PeerData*> peer,
Ui::ReportReason reason,
const QString &comment,
MessageIdsList ids = {});
} // namespace HistoryView

View File

@@ -364,9 +364,8 @@ rpl::producer<Ui::GroupCallBarContent> GroupCallBarContentByPeer(
-> rpl::producer<Ui::GroupCallBarContent> {
if (!call) {
return rpl::single(Ui::GroupCallBarContent{ .shown = false });
} else if (!call->fullCount() && !call->participantsLoaded()) {
call->reload();
}
call->reloadIfStale();
return GroupCallBarContentByCall(call, userpicSize);
}) | rpl::flatten_latest();
}

View File

@@ -154,4 +154,56 @@ rpl::producer<Ui::MessageBarContent> PinnedBarContent(
}) | rpl::flatten_latest();
}
rpl::producer<HistoryItem*> PinnedBarItemWithReplyMarkup(
not_null<Main::Session*> session,
rpl::producer<PinnedId> id) {
return rpl::make_producer<HistoryItem*>([=,
id = std::move(id)](auto consumer) {
auto lifetime = rpl::lifetime();
consumer.put_next(nullptr);
struct State {
HistoryMessageReplyMarkup *previousReplyMarkup = nullptr;
rpl::lifetime lifetime;
};
const auto state = lifetime.make_state<State>();
const auto pushUnique = [=](not_null<HistoryItem*> item) {
const auto replyMarkup = item->inlineReplyMarkup();
if (state->previousReplyMarkup == replyMarkup) {
return;
}
consumer.put_next(item.get());
state->previousReplyMarkup = replyMarkup;
};
rpl::duplicate(
id
) | rpl::start_with_next([=](PinnedId current) {
const auto fullId = current.message;
if (!fullId) {
return;
}
const auto messageFlag = [=](not_null<HistoryItem*> item) {
using Update = Data::MessageUpdate;
session->changes().messageFlagsValue(
item,
Update::Flag::ReplyMarkup
) | rpl::start_with_next([=](const Update &update) {
pushUnique(update.item);
}, state->lifetime);
};
if (const auto item = session->data().message(fullId)) {
messageFlag(item);
} else {
session->api().requestMessageData(
session->data().peer(fullId.peer),
fullId.msg,
[=] { messageFlag(session->data().message(fullId)); });
}
}, lifetime);
return lifetime;
});
}
} // namespace HistoryView

View File

@@ -49,4 +49,8 @@ struct PinnedId {
not_null<Main::Session*> session,
rpl::producer<PinnedId> id);
[[nodiscard]] rpl::producer<HistoryItem*> PinnedBarItemWithReplyMarkup(
not_null<Main::Session*> session,
rpl::producer<PinnedId> id);
} // namespace HistoryView

View File

@@ -388,7 +388,8 @@ void RepliesWidget::setupRootView() {
) | rpl::map([=](Ui::MessageBarContent &&content, bool shown) {
return shown ? std::move(content) : Ui::MessageBarContent();
});
_rootView = std::make_unique<Ui::PinnedBar>(this, std::move(content));
_rootView = std::make_unique<Ui::PinnedBar>(this);
_rootView->setContent(std::move(content));
controller()->adaptive().oneColumnValue(
) | rpl::start_with_next([=](bool one) {

View File

@@ -316,8 +316,7 @@ infoProfileSeparatorPadding: margins(
infoIconFg: windowBoldFg;
infoIconInformation: icon {{ "info/info_information", infoIconFg }};
//infoIconMembers: icon {{ "info/edit/group_manage_members", infoIconFg, point(-2px, 0px) }};
infoIconRequests: icon {{ "info/info_add_member", infoIconFg, point(0px, 2px) }};
infoIconRequests: icon {{ "info/info_add_member", infoIconFg }};
infoIconNotifications: icon {{ "info/info_notifications", infoIconFg }};
infoIconMediaPhoto: icon {{ "info/info_media_photo", infoIconFg }};
infoIconMediaVideo: icon {{ "info/info_media_video", infoIconFg }};
@@ -328,12 +327,12 @@ infoIconMediaLink: icon {{ "info/info_media_link", infoIconFg }};
infoIconMediaGroup: icon {{ "info/info_common_groups", infoIconFg }};
infoIconMediaVoice: icon {{ "info/info_media_voice", infoIconFg }};
infoIconMediaRound: icon {{ "info/info_media_round", infoIconFg }};
infoIconRecentActions: icon {{ "info/edit/group_manage_actions", infoIconFg, point(-2px, -1px) }};
infoIconAdministrators: icon {{ "info/edit/group_manage_admins", infoIconFg, point(-3px, 0px) }};
infoIconBlacklist: icon {{ "info/info_blacklist", infoIconFg, point(-2px, -2px) }};
infoIconPermissions: icon {{ "info/edit/group_manage_permissions", infoIconFg, point(0px, -2px) }};
infoIconInviteLinks: icon {{ "info/edit/group_manage_links", infoIconFg, point(-2px, 0px) }};
infoIconReactions: icon {{ "info/edit/group_manage_reactions", infoIconFg }};
infoIconRecentActions: icon {{ "info/edit/group_manage_actions", settingsIconFg }};
infoIconAdministrators: icon {{ "info/edit/group_manage_admins", settingsIconFg }};
infoIconInviteLinks: icon {{ "info/edit/group_manage_links", settingsIconFg }};
infoIconReactions: icon {{ "info/edit/group_manage_reactions", settingsIconFg }};
infoIconGroupType: icon {{ "info/edit/group_manage_type", settingsIconFg }};
infoIconSignature: icon {{ "info/edit/channel_manage_signature", settingsIconFg }};
infoIconShare: icon {{ "info/info_share", infoIconFg }};
infoIconEdit: icon {{ "info/info_edit", infoIconFg }};
infoIconDelete: icon {{ "info/info_delete", infoIconFg }};
@@ -545,23 +544,20 @@ managePeerButton: SettingsCountButton {
peerPermissionsButton: SettingsCountButton(managePeerButton) {
button: SettingsButton(infoProfileButton) {
padding: margins(24px, 12px, 24px, 10px);
padding: margins(22px, 12px, 24px, 10px);
}
iconPosition: point(24px, 5px);
}
manageGroupButton: SettingsCountButton(managePeerButton) {
button: SettingsButton(infoProfileButton) {
padding: margins(72px, 10px, 24px, 8px);
padding: margins(60px, 10px, 24px, 8px);
}
labelPosition: point(22px, 12px);
iconPosition: point(20px, 4px);
}
manageGroupTopButtonWithText: SettingsCountButton(manageGroupButton) {
button: SettingsButton(infoProfileButton) {
padding: margins(22px, 10px, 24px, 8px);
}
labelPosition: point(22px, 10px);
iconPosition: point(0px, 0px);
}
@@ -608,7 +604,9 @@ editPeerHistoryVisibilityTopSkip: 8px;
editPeerPhotoMargins: margins(22px, 16px, 22px, 8px);
editPeerTitle: defaultInputField;
editPeerTitleMargins: margins(27px, 21px, 22px, 8px);
editPeerDescription: newGroupDescription;
editPeerDescription: InputField(newGroupDescription) {
borderFg: transparent;
}
editPeerDescriptionMargins: margins(22px, 5px, 22px, 16px);
editPeerPrivaciesMargins: margins(15px, 7px, 22px, 0px);
editPeerPrivacyTopSkip: 10px;
@@ -657,8 +655,8 @@ editPeerInviteLinkBoxBottomSkip: 15px;
editPeerReactionsButton: SettingsButton(infoProfileButton) {
padding: margins(59px, 13px, 8px, 11px);
}
editPeerReactionsPreview: 48px;
editPeerReactionsIconLeft: 12px;
editPeerReactionsPreview: 24px;
editPeerReactionsIconLeft: 21px;
historyTopBarBack: IconButton(infoTopBarBack) {
width: 52px;

View File

@@ -75,12 +75,13 @@ void ContentWidget::updateControlsGeometry() {
if (!_innerWrap) {
return;
}
_innerWrap->resizeToWidth(width());
auto newScrollTop = _scroll->scrollTop() + _topDelta;
auto scrollGeometry = rect().marginsRemoved(
QMargins(0, _scrollTopSkip.current(), 0, 0));
if (_scroll->geometry() != scrollGeometry) {
_scroll->setGeometry(scrollGeometry);
_innerWrap->resizeToWidth(_scroll->width());
}
if (!_scroll->isHidden()) {

View File

@@ -105,10 +105,6 @@ void LayerWidget::setupHeightConsumers() {
// New content arrived.
_heightAnimated = _heightAnimation.animating();
return;
} else if (height < _desiredHeight
&& height < st::columnMinimalWidthMain) {
// Don't animate layer height to a very small one.
return;
}
std::swap(_desiredHeight, height);
if (!height

View File

@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_changes.h"
#include "data/data_user.h"
#include "data/notify/data_notify_settings.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
@@ -33,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/edit_contact_box.h"
#include "boxes/report_messages_box.h"
#include "lang/lang_keys.h"
#include "menu/menu_mute.h"
#include "info/info_controller.h"
@@ -376,9 +378,21 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupMuteToggle() {
tr::lng_profile_enable_notifications(),
st::infoNotificationsButton);
result->toggleOn(NotificationsEnabledValue(peer), true);
result->setAcceptBoth();
MuteMenu::SetupMuteMenu(
result.data(),
result->clicks() | rpl::to_empty,
result->clicks(
) | rpl::filter([=](Qt::MouseButton button) {
if (button == Qt::RightButton) {
return true;
}
if (peer->owner().notifySettings().isMuted(peer)) {
peer->owner().notifySettings().update(peer, 0);
return false;
} else {
return true;
}
}) | rpl::to_empty,
{ peer, std::make_shared<Window::Show>(_controller) });
object_ptr<FloatingIcon>(
result,
@@ -619,7 +633,7 @@ void ActionsFiller::addReportAction() {
const auto peer = _peer;
const auto controller = _controller->parentController();
const auto report = [=] {
HistoryView::ShowReportPeerBox(controller, peer);
ShowReportPeerBox(controller, peer);
};
AddActionButton(
_wrap,

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/click_handler_types.h"
#include "countries/countries_instance.h"
#include "main/main_session.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/text/format_values.h" // Ui::FormatPhone
@@ -81,9 +82,11 @@ rpl::producer<TextWithEntities> NameValue(not_null<PeerData*> peer) {
}
rpl::producer<TextWithEntities> PhoneValue(not_null<UserData*> user) {
return user->session().changes().peerFlagsValue(
user,
UpdateFlag::PhoneNumber
return rpl::merge(
Countries::Instance().updated(),
user->session().changes().peerFlagsValue(
user,
UpdateFlag::PhoneNumber) | rpl::to_empty
) | rpl::map([=] {
return Ui::FormatPhone(user->phone());
}) | Ui::Text::ToWithEntities();

View File

@@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/gl/gl_surface.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/delete_messages_box.h"
#include "boxes/report_messages_box.h"
#include "media/audio/media_audio.h"
#include "media/view/media_view_playback_controls.h"
#include "media/view/media_view_group_thumbs.h"
@@ -509,10 +510,7 @@ void OverlayWidget::updateGeometry(bool inMove) {
if (Platform::IsWayland()) {
return;
}
const auto screen = _widget->screen()
? _widget->screen()
: QApplication::primaryScreen();
const auto available = screen->geometry();
const auto available = _widget->screen()->geometry();
const auto openglWidget = _opengl
? static_cast<QOpenGLWidget*>(_widget.get())
: nullptr;
@@ -1037,6 +1035,25 @@ void OverlayWidget::fillContextMenuActions(const MenuCallback &addAction) {
peer->session().api().peerPhoto().set(peer, photo);
}, &st::mediaMenuIconProfile);
}();
[&] { // Report userpic.
if (!_peer
|| !_photo
|| _peer->isSelf()
|| _peer->isNotificationsUser()
|| !userPhotosKey()) {
return;
}
const auto photo = _photo;
const auto peer = _peer;
addAction(tr::lng_mediaview_report_profile_photo(tr::now), [=] {
if (const auto window = findWindow()) {
close();
window->show(
ReportProfilePhotoBox(peer, photo),
Ui::LayerOption::CloseOther);
}
}, &st::mediaMenuIconReport);
}();
}
auto OverlayWidget::computeOverviewType() const
@@ -4746,6 +4763,7 @@ void OverlayWidget::clearBeforeHide() {
_userPhotosData = std::nullopt;
_collage = nullptr;
_collageData = std::nullopt;
clearStreaming();
assignMediaPointer(nullptr);
_preloadPhotos.clear();
_preloadDocuments.clear();

View File

@@ -477,14 +477,11 @@ void PipPanel::setPositionDefault() {
if (parentScreen && myScreen && myScreen != parentScreen) {
widget()->setScreen(parentScreen);
}
const auto screen = parentScreen
? parentScreen
: QGuiApplication::primaryScreen();
auto position = Position();
position.snapped = RectPart::Top | RectPart::Left;
position.screen = screen->geometry();
position.screen = parentScreen->geometry();
position.geometry = QRect(0, 0, st::pipDefaultSize, st::pipDefaultSize);
setPositionOnScreen(position, screen->availableGeometry());
setPositionOnScreen(position, parentScreen->availableGeometry());
}
void PipPanel::setPositionOnScreen(Position position, QRect available) {

View File

@@ -128,6 +128,9 @@ void MuteItem::paintEvent(QPaintEvent *e) {
st::settingsIconBg2,
progress);
p.setPen(color);
Action::paintBackground(p, Action::isSelected());
RippleButton::paintRipple(p, 0, 0);
Action::paintText(p);
const auto &icon = _isMuted ? st::menuIconUnmute : st::menuIconMute;
@@ -177,14 +180,14 @@ void PickMuteBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
(3600 * 4),
(3600 * 8),
(3600 * 12),
(84600 * 1),
(84600 * 2),
(84600 * 3),
(84600 * 7 * 1),
(84600 * 7 * 2),
(84600 * 30 * 1),
(84600 * 30 * 2),
(84600 * 30 * 3),
(86400 * 1),
(86400 * 2),
(86400 * 3),
(86400 * 7 * 1),
(86400 * 7 * 2),
(86400 * 31 * 1),
(86400 * 31 * 2),
(86400 * 31 * 3),
};
const auto phrases = ranges::views::all(
seconds
@@ -279,9 +282,13 @@ void FillMuteMenu(
menu->addAction(std::move(item));
}
const auto callback = [=, show = args.show] {
DEBUG_LOG(("Mute Info: PickMuteBox called."));
show->showBox(Box(PickMuteBox, peer));
};
menu->addAction(
tr::lng_mute_menu_duration(tr::now),
[=, show = args.show] { show->showBox(Box(PickMuteBox, peer)); },
callback,
&st::menuIconMuteFor);
menu->addAction(

View File

@@ -173,13 +173,13 @@ void TTLBox(not_null<Ui::GenericBox*> box, Args args) {
(86400 * 7 * 1),
(86400 * 7 * 2),
(86400 * 7 * 3),
(86400 * 30 * 1),
(86400 * 30 * 2),
(86400 * 30 * 3),
(86400 * 30 * 4),
(86400 * 30 * 5),
(86400 * 30 * 6),
(86400 * 30 * 12),
(86400 * 31 * 1),
(86400 * 31 * 2),
(86400 * 31 * 3),
(86400 * 31 * 4),
(86400 * 31 * 5),
(86400 * 31 * 6),
(86400 * 365),
};
const auto phrases = ranges::views::all(
ttls

View File

@@ -776,6 +776,9 @@ void Panel::showWebviewError(
case Error::Wayland:
rich.append(tr::lng_payments_webview_switch_wayland(tr::now));
break;
case Error::OldWindows:
rich.append(tr::lng_payments_webview_update_windows(tr::now));
break;
default:
rich.append(QString::fromStdString(information.details));
break;

View File

@@ -679,8 +679,12 @@ void NotificationData::setImage(const QString &imagePath) {
return;
}
const auto image = QImage(imagePath)
.convertToFormat(QImage::Format_RGBA8888);
const auto image = [&] {
const auto original = QImage(imagePath);
return original.hasAlphaChannel()
? original.convertToFormat(QImage::Format_RGBA8888)
: original.convertToFormat(QImage::Format_RGB888);
}();
if (image.isNull()) {
return;
@@ -690,9 +694,9 @@ void NotificationData::setImage(const QString &imagePath) {
image.width(),
image.height(),
int(image.bytesPerLine()),
true,
image.hasAlphaChannel(),
8,
4,
image.hasAlphaChannel() ? 4 : 3,
std::vector<uchar>(
image.constBits(),
image.constBits() + image.sizeInBytes()),

View File

@@ -382,12 +382,6 @@ QString GetIconName() {
std::optional<bool> IsDarkMode() {
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
[[maybe_unused]] static const auto Inited = [] {
static const auto Setter = [] {
crl::on_main([] {
Core::App().settings().setSystemDarkMode(IsDarkMode());
});
};
using XDPSettingWatcher = base::Platform::XDP::SettingWatcher;
static const XDPSettingWatcher Watcher(
[=](
@@ -396,7 +390,14 @@ std::optional<bool> IsDarkMode() {
const Glib::VariantBase &value) {
if (group == "org.freedesktop.appearance"
&& key == "color-scheme") {
Setter();
try {
const auto ivalue = base::Platform::GlibVariantCast<uint>(value);
crl::on_main([=] {
Core::App().settings().setSystemDarkMode(ivalue == 1);
});
} catch (...) {
}
}
});
@@ -410,10 +411,7 @@ std::optional<bool> IsDarkMode() {
if (result.has_value()) {
const auto value = base::Platform::GlibVariantCast<uint>(*result);
if (value == 1) {
return true;
}
return false;
return value == 1;
}
} catch (...) {
}

View File

@@ -630,7 +630,7 @@ void MainWindow::showFromTrayMenu() {
// It will receive input events, but it will be rendered as inactive.
using namespace rpl::mappers;
_showFromTrayLifetime = trayIconMenu->shownValue(
) | rpl::filter(_1) | rpl::take(1) | rpl::start_with_next([=] {
) | rpl::filter(!_1) | rpl::take(1) | rpl::start_with_next([=] {
showFromTray();
});
}

View File

@@ -903,7 +903,6 @@ void SetupMessages(
r.top() + (r.height() - iconSize) / 2);
}),
iconSize,
&controller->session(),
r,
buttonRight->events(
) | rpl::filter([=](not_null<QEvent*> event) {

View File

@@ -40,9 +40,15 @@ void ReportReasonBox(
case Source::Channel: return tr::lng_report_title();
case Source::Group: return tr::lng_report_group_title();
case Source::Bot: return tr::lng_report_bot_title();
case Source::ProfilePhoto:
return tr::lng_report_profile_photo_title();
case Source::ProfileVideo:
return tr::lng_report_profile_video_title();
}
Unexpected("'source' in ReportReasonBox.");
}());
const auto isProfileSource = (source == Source::ProfilePhoto)
|| (source == Source::ProfileVideo);
auto margin = style::margins{ 0, st::reportReasonTopSkip, 0, 0 };
const auto add = [&](
Reason reason,
@@ -69,7 +75,7 @@ void ReportReasonBox(
});
};
add(Reason::Spam, tr::lng_report_reason_spam, st::menuIconDelete);
if (source != Source::Message) {
if (source != Source::Message && !isProfileSource) {
add(Reason::Fake, tr::lng_report_reason_fake, st::menuIconFake);
}
add(

View File

@@ -16,6 +16,8 @@ enum class ReportSource {
Channel,
Group,
Bot,
ProfilePhoto,
ProfileVideo,
};
enum class ReportReason {

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/event_filter.h"
#include "lang/lang_keys.h"
#include "ui/layers/generic_box.h"
#include "ui/effects/animation_value.h"
#include "ui/ui_utility.h"
#include "ui/widgets/vertical_drum_picker.h"
#include "styles/style_chat.h"
@@ -17,6 +18,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui {
namespace {
constexpr auto kMinYScale = 0.2;
} // namespace
Fn<TimeId()> TimePickerBox(
not_null<GenericBox*> box,
std::vector<TimeId> values,
@@ -24,9 +31,17 @@ Fn<TimeId()> TimePickerBox(
TimeId startValue) {
Expects(phrases.size() == values.size());
const auto startIndex = [&] {
const auto it = ranges::find(values, startValue);
return (it == end(values)) ? 0 : std::distance(begin(values), it);
const auto startIndex = [&, &v = startValue] {
const auto it = ranges::lower_bound(values, v);
if (it == begin(values)) {
return 0;
}
const auto left = *(it - 1);
const auto right = *it;
const auto shift = (std::abs(v - left) < std::abs(v - right))
? -1
: 0;
return int(std::distance(begin(values), it - shift));
}();
const auto content = box->addRow(object_ptr<Ui::FixedHeightWidget>(
@@ -35,11 +50,14 @@ Fn<TimeId()> TimePickerBox(
const auto font = st::boxTextFont;
const auto maxPhraseWidth = [&] {
// We have to use QFontMetricsF instead of
// FontData::width for more precise calculation.
const auto mf = QFontMetricsF(font->f);
const auto maxPhrase = ranges::max_element(
phrases,
std::less<>(),
[&](const QString &s) { return font->width(s); });
return font->width(*maxPhrase) + font->spacew * 2;
[&](const QString &s) { return mf.horizontalAdvance(s); });
return std::ceil(mf.horizontalAdvance(*maxPhrase));
}();
const auto itemHeight = st::historyMessagesTTLPickerItemHeight;
auto paintCallback = [=](
@@ -50,10 +68,18 @@ Fn<TimeId()> TimePickerBox(
int outerWidth) {
const auto r = QRectF(0, y, outerWidth, itemHeight);
const auto progress = std::abs(distanceFromCenter);
p.setOpacity(1. - progress);
const auto revProgress = 1. - progress;
p.save();
p.translate(r.center());
const auto yScale = kMinYScale
+ (1. - kMinYScale) * anim::easeOutCubic(1., revProgress);
p.scale(1., yScale);
p.translate(-r.center());
p.setOpacity(revProgress);
p.setFont(font);
p.setPen(st::defaultFlatLabel.textFg);
p.drawText(r, phrases[index], style::al_center);
p.restore();
};
const auto picker = Ui::CreateChild<Ui::VerticalDrumPicker>(

View File

@@ -322,7 +322,9 @@ Panel::Panel(
_widget->closeEvents(
) | rpl::start_with_next(_close, _widget->lifetime());
style::PaletteChanged(
rpl::combine(
style::PaletteChanged(),
_themeUpdateForced.events()
) | rpl::filter([=] {
return !_themeUpdateScheduled;
}) | rpl::start_with_next([=] {
@@ -564,6 +566,8 @@ bool Panel::createWebview() {
sendDataMessage(list.at(1));
} else if (command == "web_app_setup_main_button") {
processMainButtonMessage(list.at(1));
} else if (command == "web_app_request_theme") {
_themeUpdateForced.fire({});
}
});

View File

@@ -88,6 +88,7 @@ private:
QPointer<QWidget> _webviewParent;
std::unique_ptr<Button> _mainButton;
std::unique_ptr<Progress> _progress;
rpl::event_stream<> _themeUpdateForced;
rpl::lifetime _fgLifetime;
rpl::lifetime _bgLifetime;
bool _webviewProgress = false;

View File

@@ -325,7 +325,8 @@ historyMessagesTTL: IconButtonWithText {
}
textFg: historyComposeIconFg;
textFgOver: historyComposeIconFgOver;
textPadding: margins(16px, 20px, 6px, 7px);
textPadding: margins(21px, 20px, 3px, 7px);
textAlign: align(left);
font: font(10px semibold);
}
@@ -476,6 +477,13 @@ historyPinnedShowAll: IconButton(historyReplyCancel) {
icon: icon {{ "pinned_show_all", historyReplyCancelFg }};
iconOver: icon {{ "pinned_show_all", historyReplyCancelFgOver }};
}
historyPinnedBotButton: RoundButton(defaultActiveButton) {
width: -34px;
height: 30px;
textTop: 6px;
padding: margins(2px, 10px, 10px, 9px);
}
historyPinnedBotButtonMaxWidth: 150px;
msgBotKbDuration: 200;
msgBotKbFont: semiboldFont;

View File

@@ -222,7 +222,7 @@ QRect MessageBar::bodyRect(bool withImage) const {
const auto top = st::msgReplyPadding.top();
const auto width = _widget.width() - left - st::msgReplyPadding.right();
const auto height = st::msgReplyBarSize.height();
return QRect(left, top, width, height);
return QRect(left, top, width, height) - _content.margins;
}
QRect MessageBar::bodyRect() const {

View File

@@ -24,6 +24,7 @@ struct MessageBarContent {
QString title;
TextWithEntities text;
QImage preview;
style::margins margins;
};
class MessageBar final {

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/message_bar.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/fade_wrap.h"
#include "styles/style_chat.h"
#include "styles/palette.h"
@@ -17,9 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui {
PinnedBar::PinnedBar(
not_null<QWidget*> parent,
rpl::producer<MessageBarContent> content)
PinnedBar::PinnedBar(not_null<QWidget*> parent)
: _wrap(parent, object_ptr<RpWidget>(parent))
, _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget())) {
_wrap.hide(anim::type::instant);
@@ -30,10 +29,18 @@ PinnedBar::PinnedBar(
QPainter(_wrap.entity()).fillRect(clip, st::historyPinnedBg);
}, lifetime());
_wrap.setAttribute(Qt::WA_OpaquePaintEvent);
}
PinnedBar::~PinnedBar() {
_right.button.destroy();
}
void PinnedBar::setContent(rpl::producer<Ui::MessageBarContent> content) {
_contentLifetime.destroy();
auto copy = std::move(
content
) | rpl::start_spawning(_wrap.lifetime());
) | rpl::start_spawning(_contentLifetime);
rpl::duplicate(
copy
@@ -44,11 +51,17 @@ PinnedBar::PinnedBar(
if (creating) {
createControls();
}
// In most cases the new right button should arrive
// before we want to get its width.
const auto right = _right.button ? _right.button->width() : 0;
content.margins = { 0, 0, right, 0 };
_bar->set(std::move(content));
if (creating) {
_bar->finishAnimating();
}
}, lifetime());
}, _contentLifetime);
std::move(
copy
@@ -64,19 +77,24 @@ PinnedBar::PinnedBar(
}, [=] {
_forceHidden = true;
_wrap.toggle(false, anim::type::normal);
}, lifetime());
}
PinnedBar::~PinnedBar() {
_rightButton.destroy();
}, _contentLifetime);
}
void PinnedBar::setRightButton(object_ptr<Ui::RpWidget> button) {
_rightButton.destroy();
_rightButton = std::move(button);
if (_rightButton) {
_rightButton->setParent(_wrap.entity());
_rightButton->show();
if (auto previous = _right.button.release()) {
_right.previousButtonLifetime.make_state<RightButton>(
RightButton::fromRaw(std::move(previous)));
_right.previousButtonLifetime = previous->toggledValue(
) | rpl::filter(!rpl::mappers::_1) | rpl::start_with_next([=] {
_right.previousButtonLifetime.destroy();
});
previous->hide(anim::type::normal);
}
_right.button.create(_wrap.entity(), std::move(button));
if (_right.button) {
_right.button->setParent(_wrap.entity());
_right.button->setDuration(st::defaultMessageBar.duration);
_right.button->show(anim::type::normal);
}
if (_bar) {
updateControlsGeometry(_wrap.geometry());
@@ -84,14 +102,13 @@ void PinnedBar::setRightButton(object_ptr<Ui::RpWidget> button) {
}
void PinnedBar::updateControlsGeometry(QRect wrapGeometry) {
_bar->widget()->resizeToWidth(
wrapGeometry.width() - (_rightButton ? _rightButton->width() : 0));
_bar->widget()->resizeToWidth(wrapGeometry.width());
const auto hidden = _wrap.isHidden() || !wrapGeometry.height();
if (_shadow->isHidden() != hidden) {
_shadow->setVisible(!hidden);
}
if (_rightButton) {
_rightButton->moveToRight(0, 0);
if (_right.button) {
_right.button->moveToRight(0, 0);
}
}
@@ -117,8 +134,8 @@ void PinnedBar::createControls() {
_bar = std::make_unique<MessageBar>(
_wrap.entity(),
st::defaultMessageBar);
if (_rightButton) {
_rightButton->raise();
if (_right.button) {
_right.button->raise();
}
// Clicks.

View File

@@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui {
struct MessageBarContent;
template <typename Widget>
class FadeWrapScaled;
class MessageBar;
class IconButton;
class PlainShadow;
@@ -20,9 +22,7 @@ class RpWidget;
class PinnedBar final {
public:
PinnedBar(
not_null<QWidget*> parent,
rpl::producer<Ui::MessageBarContent> content);
PinnedBar(not_null<QWidget*> parent);
~PinnedBar();
void show();
@@ -32,6 +32,7 @@ public:
void setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess);
void setContent(rpl::producer<Ui::MessageBarContent> content);
void setRightButton(object_ptr<Ui::RpWidget> button);
void move(int x, int y);
@@ -45,19 +46,27 @@ public:
}
private:
using RightButton = object_ptr<Ui::FadeWrapScaled<Ui::RpWidget>>;
void createControls();
void updateShadowGeometry(QRect wrapGeometry);
void updateControlsGeometry(QRect wrapGeometry);
Ui::SlideWrap<> _wrap;
std::unique_ptr<Ui::MessageBar> _bar;
object_ptr<Ui::RpWidget> _rightButton = { nullptr };
struct {
RightButton button = { nullptr };
rpl::lifetime previousButtonLifetime;
} _right;
std::unique_ptr<Ui::PlainShadow> _shadow;
rpl::event_stream<> _barClicks;
Fn<QRect(QRect)> _shadowGeometryPostprocess;
bool _shouldBeShown = false;
bool _forceHidden = false;
rpl::lifetime _contentLifetime;
};
} // namespace Ui

View File

@@ -131,6 +131,7 @@ mediaMenuIconForward: icon {{ "menu/forward", mediaviewMenuFg }};
mediaMenuIconDelete: icon {{ "menu/delete", mediaviewMenuFg }};
mediaMenuIconShowAll: icon {{ "menu/all_media", mediaviewMenuFg }};
mediaMenuIconProfile: icon {{ "menu/profile", mediaviewMenuFg }};
mediaMenuIconReport: icon {{ "menu/report", mediaviewMenuFg }};
menuIconStartStream: icon {{ "menu/start_stream", menuIconColor }};
menuIconStartStreamWith: icon {{ "menu/start_stream_with", menuIconColor }};

View File

@@ -386,33 +386,33 @@ QString FormatPhone(const QString &phone) {
QString FormatTTL(float64 ttl) {
return (ttl <= 3600 * 23)
? tr::lng_hours(tr::now, lt_count, std::ceil(ttl / 3600))
? tr::lng_hours(tr::now, lt_count, int(ttl / 3600))
: (ttl <= (86400) * 6)
? tr::lng_days(tr::now, lt_count, std::ceil(ttl / (86400)))
? tr::lng_days(tr::now, lt_count, int(ttl / (86400)))
: (ttl <= (86400 * 7) * 3)
? tr::lng_weeks(tr::now, lt_count, std::ceil(ttl / (86400 * 7)))
: (ttl <= (86400 * 30) * 11)
? tr::lng_months({}, lt_count, std::ceil(ttl / (86400 * 30)))
: tr::lng_years({}, lt_count, std::ceil(ttl / (86400 * 30 * 12)));
? tr::lng_weeks(tr::now, lt_count, int(ttl / (86400 * 7)))
: (ttl <= (86400 * 31) * 11)
? tr::lng_months({}, lt_count, int(ttl / (86400 * 31)))
: tr::lng_years({}, lt_count, std::round(ttl / (86400 * 365)));
}
QString FormatTTLTiny(float64 ttl) {
return (ttl <= 3600 * 9)
? tr::lng_hours_tiny(tr::now, lt_count, std::ceil(ttl / 3600))
? tr::lng_hours_tiny(tr::now, lt_count, int(ttl / 3600))
: (ttl <= (86400) * 6)
? tr::lng_days_tiny(tr::now, lt_count, std::ceil(ttl / (86400)))
? tr::lng_days_tiny(tr::now, lt_count, int(ttl / (86400)))
: (ttl <= (86400 * 7) * 3)
? tr::lng_weeks_tiny(tr::now, lt_count, std::ceil(ttl / (86400 * 7)))
: (ttl <= (86400 * 30) * 11)
? tr::lng_months_tiny({}, lt_count, std::ceil(ttl / (86400 * 30)))
: tr::lng_years_tiny({}, lt_count, std::ceil(ttl / (86400 * 360)));
? tr::lng_weeks_tiny(tr::now, lt_count, int(ttl / (86400 * 7)))
: (ttl <= (86400 * 31) * 11)
? tr::lng_months_tiny({}, lt_count, int(ttl / (86400 * 31)))
: tr::lng_years_tiny({}, lt_count, std::round(ttl / (86400 * 365)));
}
QString FormatMuteFor(float64 sec) {
return (sec <= 60)
? tr::lng_seconds(tr::now, lt_count, sec)
: (sec <= 60 * 59)
? tr::lng_minutes(tr::now, lt_count, std::ceil(sec / 60))
? tr::lng_minutes(tr::now, lt_count, int(sec / 60))
: FormatTTL(sec);
}
@@ -420,13 +420,13 @@ QString FormatMuteForTiny(float64 sec) {
return (sec <= 60)
? QString()
: (sec <= 60 * 59)
? tr::lng_minutes_tiny(tr::now, lt_count, std::ceil(sec / 60))
? tr::lng_minutes_tiny(tr::now, lt_count, int(sec / 60))
: (sec <= 3600 * 23)
? tr::lng_hours_tiny(tr::now, lt_count, std::ceil(sec / 3600))
? tr::lng_hours_tiny(tr::now, lt_count, int(sec / 3600))
: (sec <= 86400 * 6)
? tr::lng_days_tiny(tr::now, lt_count, std::ceil(sec / 86400))
? tr::lng_days_tiny(tr::now, lt_count, int(sec / 86400))
: (sec <= (86400 * 7) * 3)
? tr::lng_weeks_tiny(tr::now, lt_count, std::ceil(sec / (86400 * 7)))
? tr::lng_weeks_tiny(tr::now, lt_count, int(sec / (86400 * 7)))
: QString();
}

View File

@@ -7,15 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/widgets/multi_select.h"
#include "styles/style_widgets.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/scroll_area.h"
#include "ui/effects/animations.h"
#include "ui/effects/cross_animation.h"
#include "ui/text/text_options.h"
#include "ui/ui_utility.h"
#include "lang/lang_keys.h"
#include <set>
namespace Ui {
namespace {

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