mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Merge tag 'v4.8.11' into dev
# Conflicts: # Telegram/Resources/winrc/Telegram.rc # Telegram/Resources/winrc/Updater.rc # Telegram/SourceFiles/core/version.h # Telegram/lib_ui
This commit is contained in:
commit
e5ff26b2eb
70 changed files with 701 additions and 483 deletions
|
@ -19,9 +19,9 @@ include(cmake/validate_special_target.cmake)
|
||||||
include(cmake/version.cmake)
|
include(cmake/version.cmake)
|
||||||
desktop_app_parse_version(Telegram/build/version)
|
desktop_app_parse_version(Telegram/build/version)
|
||||||
|
|
||||||
set(project_langs C CXX)
|
set(project_langs ASM C CXX)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(project_langs C CXX OBJC OBJCXX)
|
list(APPEND project_langs OBJC OBJCXX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Telegram
|
project(Telegram
|
||||||
|
@ -43,9 +43,10 @@ endif()
|
||||||
include(cmake/variables.cmake)
|
include(cmake/variables.cmake)
|
||||||
include(cmake/nice_target_sources.cmake)
|
include(cmake/nice_target_sources.cmake)
|
||||||
include(cmake/target_compile_options_if_exists.cmake)
|
include(cmake/target_compile_options_if_exists.cmake)
|
||||||
|
include(cmake/target_link_frameworks.cmake)
|
||||||
|
include(cmake/target_link_optional_libraries.cmake)
|
||||||
include(cmake/target_link_options_if_exists.cmake)
|
include(cmake/target_link_options_if_exists.cmake)
|
||||||
include(cmake/target_link_static_libraries.cmake)
|
include(cmake/target_link_static_libraries.cmake)
|
||||||
include(cmake/target_link_frameworks.cmake)
|
|
||||||
include(cmake/init_target.cmake)
|
include(cmake/init_target.cmake)
|
||||||
include(cmake/generate_target.cmake)
|
include(cmake/generate_target.cmake)
|
||||||
include(cmake/nuget.cmake)
|
include(cmake/nuget.cmake)
|
||||||
|
|
|
@ -189,6 +189,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_filter_chats_limit_title" = "Limit Reached";
|
"lng_filter_chats_limit_title" = "Limit Reached";
|
||||||
"lng_filter_chats_limit1#one" = "Sorry, you can't add more than **{count}** chat to a folder.";
|
"lng_filter_chats_limit1#one" = "Sorry, you can't add more than **{count}** chat to a folder.";
|
||||||
"lng_filter_chats_limit1#other" = "Sorry, you can't add more than **{count}** chats to a folder.";
|
"lng_filter_chats_limit1#other" = "Sorry, you can't add more than **{count}** chats to a folder.";
|
||||||
|
"lng_filter_chats_exlude_limit1#one" = "Sorry, you can't exlude more than **{count}** chat from a folder.";
|
||||||
|
"lng_filter_chats_exlude_limit1#other" = "Sorry, you can't exlude more than **{count}** chats from a folder.";
|
||||||
"lng_filter_chats_limit2#one" = "You can increase this limit to **{count}** by upgrading to **Telegram Premium**.";
|
"lng_filter_chats_limit2#one" = "You can increase this limit to **{count}** by upgrading to **Telegram Premium**.";
|
||||||
"lng_filter_chats_limit2#other" = "You can increase this limit to **{count}** by upgrading to **Telegram Premium**.";
|
"lng_filter_chats_limit2#other" = "You can increase this limit to **{count}** by upgrading to **Telegram Premium**.";
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||||
ProcessorArchitecture="ARCHITECTURE"
|
ProcessorArchitecture="ARCHITECTURE"
|
||||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||||
Version="4.8.10.0" />
|
Version="4.8.11.0" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>Telegram Desktop</DisplayName>
|
<DisplayName>Telegram Desktop</DisplayName>
|
||||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||||
|
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,8,10,0
|
FILEVERSION 4,8,11,0
|
||||||
PRODUCTVERSION 4,8,10,0
|
PRODUCTVERSION 4,8,11,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -62,10 +62,10 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Radolyn Labs"
|
VALUE "CompanyName", "Radolyn Labs"
|
||||||
VALUE "FileDescription", "AyuGram Desktop"
|
VALUE "FileDescription", "AyuGram Desktop"
|
||||||
VALUE "FileVersion", "4.8.10.0"
|
VALUE "FileVersion", "4.8.11.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "4.8.10.0"
|
VALUE "ProductVersion", "4.8.11.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,8,10,0
|
FILEVERSION 4,8,11,0
|
||||||
PRODUCTVERSION 4,8,10,0
|
PRODUCTVERSION 4,8,11,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -53,10 +53,10 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Radolyn Labs"
|
VALUE "CompanyName", "Radolyn Labs"
|
||||||
VALUE "FileDescription", "AyuGram Desktop Updater"
|
VALUE "FileDescription", "AyuGram Desktop Updater"
|
||||||
VALUE "FileVersion", "4.8.10.0"
|
VALUE "FileVersion", "4.8.11.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "4.8.10.0"
|
VALUE "ProductVersion", "4.8.11.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -510,7 +510,7 @@ void ShowImportError(
|
||||||
if (error == u"CHANNELS_TOO_MUCH"_q) {
|
if (error == u"CHANNELS_TOO_MUCH"_q) {
|
||||||
window->show(Box(ChannelsLimitBox, session));
|
window->show(Box(ChannelsLimitBox, session));
|
||||||
} else if (error == u"FILTER_INCLUDE_TOO_MUCH"_q) {
|
} else if (error == u"FILTER_INCLUDE_TOO_MUCH"_q) {
|
||||||
window->show(Box(FilterChatsLimitBox, session, count));
|
window->show(Box(FilterChatsLimitBox, session, count, true));
|
||||||
} else if (error == u"CHATLISTS_TOO_MUCH"_q) {
|
} else if (error == u"CHATLISTS_TOO_MUCH"_q) {
|
||||||
window->show(Box(ShareableFiltersLimitBox, session));
|
window->show(Box(ShareableFiltersLimitBox, session));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -456,7 +456,6 @@ void SendConfirmedFile(
|
||||||
}());
|
}());
|
||||||
|
|
||||||
if (itemToEdit) {
|
if (itemToEdit) {
|
||||||
itemToEdit->savePreviousMedia();
|
|
||||||
auto edition = HistoryMessageEdition();
|
auto edition = HistoryMessageEdition();
|
||||||
edition.isEditHide = (flags & MessageFlag::HideEdited);
|
edition.isEditHide = (flags & MessageFlag::HideEdited);
|
||||||
edition.editDate = 0;
|
edition.editDate = 0;
|
||||||
|
@ -468,6 +467,7 @@ void SendConfirmedFile(
|
||||||
edition.useSameMarkup = true;
|
edition.useSameMarkup = true;
|
||||||
edition.useSameReplies = true;
|
edition.useSameReplies = true;
|
||||||
edition.useSameReactions = true;
|
edition.useSameReactions = true;
|
||||||
|
edition.savePreviousMedia = true;
|
||||||
itemToEdit->applyEdition(std::move(edition));
|
itemToEdit->applyEdition(std::move(edition));
|
||||||
} else {
|
} else {
|
||||||
const auto viaBotId = UserId();
|
const auto viaBotId = UserId();
|
||||||
|
|
|
@ -3419,7 +3419,7 @@ void ApiWrap::sendSharedContact(
|
||||||
void ApiWrap::sendVoiceMessage(
|
void ApiWrap::sendVoiceMessage(
|
||||||
QByteArray result,
|
QByteArray result,
|
||||||
VoiceWaveform waveform,
|
VoiceWaveform waveform,
|
||||||
int duration,
|
crl::time duration,
|
||||||
const SendAction &action) {
|
const SendAction &action) {
|
||||||
const auto caption = TextWithTags();
|
const auto caption = TextWithTags();
|
||||||
const auto to = fileLoadTaskOptions(action);
|
const auto to = fileLoadTaskOptions(action);
|
||||||
|
|
|
@ -302,7 +302,7 @@ public:
|
||||||
void sendVoiceMessage(
|
void sendVoiceMessage(
|
||||||
QByteArray result,
|
QByteArray result,
|
||||||
VoiceWaveform waveform,
|
VoiceWaveform waveform,
|
||||||
int duration,
|
crl::time duration,
|
||||||
const SendAction &action);
|
const SendAction &action);
|
||||||
void sendFiles(
|
void sendFiles(
|
||||||
Ui::PreparedList &&list,
|
Ui::PreparedList &&list,
|
||||||
|
|
|
@ -607,7 +607,7 @@ groupStickersField: InputField(defaultMultiSelectSearchField) {
|
||||||
textBg: boxBg;
|
textBg: boxBg;
|
||||||
heightMin: 32px;
|
heightMin: 32px;
|
||||||
}
|
}
|
||||||
groupStickersSubTitleHeight: 36px;
|
groupStickersSubTitleHeight: 48px;
|
||||||
|
|
||||||
proxyUsePadding: margins(22px, 6px, 22px, 5px);
|
proxyUsePadding: margins(22px, 6px, 22px, 5px);
|
||||||
proxyTryIPv6Padding: margins(22px, 8px, 22px, 5px);
|
proxyTryIPv6Padding: margins(22px, 8px, 22px, 5px);
|
||||||
|
|
|
@ -164,7 +164,8 @@ void FillChooseFilterMenu(
|
||||||
controller->show(Box(
|
controller->show(Box(
|
||||||
FilterChatsLimitBox,
|
FilterChatsLimitBox,
|
||||||
&controller->session(),
|
&controller->session(),
|
||||||
r.count));
|
r.count,
|
||||||
|
true));
|
||||||
} else if (validator.canAdd()) {
|
} else if (validator.canAdd()) {
|
||||||
validator.add(id);
|
validator.add(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,14 +336,18 @@ void EditExceptions(
|
||||||
Fn<void()> refresh) {
|
Fn<void()> refresh) {
|
||||||
const auto include = (options & Flag::Contacts) != Flags(0);
|
const auto include = (options & Flag::Contacts) != Flags(0);
|
||||||
const auto rules = data->current();
|
const auto rules = data->current();
|
||||||
|
const auto session = &window->session();
|
||||||
auto controller = std::make_unique<EditFilterChatsListController>(
|
auto controller = std::make_unique<EditFilterChatsListController>(
|
||||||
&window->session(),
|
session,
|
||||||
(include
|
(include
|
||||||
? tr::lng_filters_include_title()
|
? tr::lng_filters_include_title()
|
||||||
: tr::lng_filters_exclude_title()),
|
: tr::lng_filters_exclude_title()),
|
||||||
options,
|
options,
|
||||||
rules.flags() & options,
|
rules.flags() & options,
|
||||||
include ? rules.always() : rules.never());
|
include ? rules.always() : rules.never(),
|
||||||
|
[=](int count) {
|
||||||
|
return Box(FilterChatsLimitBox, session, count, include);
|
||||||
|
});
|
||||||
const auto rawController = controller.get();
|
const auto rawController = controller.get();
|
||||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
box->setCloseByOutsideClick(false);
|
box->setCloseByOutsideClick(false);
|
||||||
|
|
|
@ -7,9 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "boxes/filters/edit_filter_chats_list.h"
|
#include "boxes/filters/edit_filter_chats_list.h"
|
||||||
|
|
||||||
|
#include "data/data_premium_limits.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "boxes/premium_limits_box.h"
|
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
@ -99,22 +99,6 @@ private:
|
||||||
return PeerId(FakeChatId(static_cast<BareId>(flag))).value;
|
return PeerId(FakeChatId(static_cast<BareId>(flag))).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] int Limit(
|
|
||||||
not_null<Main::Session*> session,
|
|
||||||
const QString &key,
|
|
||||||
int fallback) {
|
|
||||||
return session->account().appConfig().get<int>(key, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int Limit(not_null<Main::Session*> session) {
|
|
||||||
const auto premium = session->premium();
|
|
||||||
return Limit(session,
|
|
||||||
(premium
|
|
||||||
? "dialog_filters_chats_limit_premium"
|
|
||||||
: "dialog_filters_chats_limit_default"),
|
|
||||||
premium ? 200 : 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeRow::TypeRow(Flag flag) : PeerListRow(TypeId(flag)) {
|
TypeRow::TypeRow(Flag flag) : PeerListRow(TypeId(flag)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,15 +322,18 @@ EditFilterChatsListController::EditFilterChatsListController(
|
||||||
rpl::producer<QString> title,
|
rpl::producer<QString> title,
|
||||||
Flags options,
|
Flags options,
|
||||||
Flags selected,
|
Flags selected,
|
||||||
const base::flat_set<not_null<History*>> &peers)
|
const base::flat_set<not_null<History*>> &peers,
|
||||||
|
LimitBoxFactory limitBox)
|
||||||
: ChatsListBoxController(session)
|
: ChatsListBoxController(session)
|
||||||
, _session(session)
|
, _session(session)
|
||||||
|
, _limitBox(std::move(limitBox))
|
||||||
, _title(std::move(title))
|
, _title(std::move(title))
|
||||||
, _peers(peers)
|
, _peers(peers)
|
||||||
, _options(options & ~Flag::Chatlist)
|
, _options(options & ~Flag::Chatlist)
|
||||||
, _selected(selected)
|
, _selected(selected)
|
||||||
, _limit(Limit(session))
|
, _limit(Data::PremiumLimits(session).dialogFiltersChatsCurrent())
|
||||||
, _chatlist(options & Flag::Chatlist) {
|
, _chatlist(options & Flag::Chatlist) {
|
||||||
|
Expects(_limitBox != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Main::Session &EditFilterChatsListController::session() const {
|
Main::Session &EditFilterChatsListController::session() const {
|
||||||
|
@ -375,8 +362,7 @@ void EditFilterChatsListController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||||
updateTitle();
|
updateTitle();
|
||||||
} else {
|
} else {
|
||||||
delegate()->peerListShowBox(
|
delegate()->peerListShowBox(_limitBox(count));
|
||||||
Box(FilterChatsLimitBox, _session, count));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,13 +43,15 @@ class EditFilterChatsListController final : public ChatsListBoxController {
|
||||||
public:
|
public:
|
||||||
using Flag = Data::ChatFilter::Flag;
|
using Flag = Data::ChatFilter::Flag;
|
||||||
using Flags = Data::ChatFilter::Flags;
|
using Flags = Data::ChatFilter::Flags;
|
||||||
|
using LimitBoxFactory = Fn<object_ptr<Ui::BoxContent>(int)>;
|
||||||
|
|
||||||
EditFilterChatsListController(
|
EditFilterChatsListController(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
rpl::producer<QString> title,
|
rpl::producer<QString> title,
|
||||||
Flags options,
|
Flags options,
|
||||||
Flags selected,
|
Flags selected,
|
||||||
const base::flat_set<not_null<History*>> &peers);
|
const base::flat_set<not_null<History*>> &peers,
|
||||||
|
LimitBoxFactory limitBox);
|
||||||
|
|
||||||
[[nodiscard]] Main::Session &session() const override;
|
[[nodiscard]] Main::Session &session() const override;
|
||||||
[[nodiscard]] Flags chosenOptions() const {
|
[[nodiscard]] Flags chosenOptions() const {
|
||||||
|
@ -70,6 +72,7 @@ private:
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
const LimitBoxFactory _limitBox;
|
||||||
rpl::producer<QString> _title;
|
rpl::producer<QString> _title;
|
||||||
base::flat_set<not_null<History*>> _peers;
|
base::flat_set<not_null<History*>> _peers;
|
||||||
Flags _options;
|
Flags _options;
|
||||||
|
|
|
@ -694,7 +694,8 @@ void PublicLinksLimitBox(
|
||||||
void FilterChatsLimitBox(
|
void FilterChatsLimitBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
int currentCount) {
|
int currentCount,
|
||||||
|
bool include) {
|
||||||
const auto premium = session->premium();
|
const auto premium = session->premium();
|
||||||
const auto premiumPossible = session->premiumPossible();
|
const auto premiumPossible = session->premiumPossible();
|
||||||
|
|
||||||
|
@ -707,10 +708,12 @@ void FilterChatsLimitBox(
|
||||||
premiumLimit);
|
premiumLimit);
|
||||||
|
|
||||||
auto text = rpl::combine(
|
auto text = rpl::combine(
|
||||||
tr::lng_filter_chats_limit1(
|
(include
|
||||||
lt_count,
|
? tr::lng_filter_chats_limit1
|
||||||
rpl::single(premium ? premiumLimit : defaultLimit),
|
: tr::lng_filter_chats_exlude_limit1)(
|
||||||
Ui::Text::RichLangValue),
|
lt_count,
|
||||||
|
rpl::single(premium ? premiumLimit : defaultLimit),
|
||||||
|
Ui::Text::RichLangValue),
|
||||||
((premium || !premiumPossible)
|
((premium || !premiumPossible)
|
||||||
? rpl::single(TextWithEntities())
|
? rpl::single(TextWithEntities())
|
||||||
: tr::lng_filter_chats_limit2(
|
: tr::lng_filter_chats_limit2(
|
||||||
|
|
|
@ -35,7 +35,8 @@ void PublicLinksLimitBox(
|
||||||
void FilterChatsLimitBox(
|
void FilterChatsLimitBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
int currentCount);
|
int currentCount,
|
||||||
|
bool include);
|
||||||
void FilterLinksLimitBox(
|
void FilterLinksLimitBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
not_null<Main::Session*> session);
|
not_null<Main::Session*> session);
|
||||||
|
|
|
@ -250,6 +250,7 @@ private:
|
||||||
int countMaxNameWidth(bool installedSet) const;
|
int countMaxNameWidth(bool installedSet) const;
|
||||||
[[nodiscard]] bool skipPremium() const;
|
[[nodiscard]] bool skipPremium() const;
|
||||||
|
|
||||||
|
const style::PeerListItem &_st;
|
||||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
@ -386,7 +387,8 @@ StickersBox::StickersBox(
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
Section section,
|
Section section,
|
||||||
bool masks)
|
bool masks)
|
||||||
: _show(std::move(show))
|
: _st(st::stickersRowItem)
|
||||||
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _tabs(this, st::stickersTabs)
|
, _tabs(this, st::stickersTabs)
|
||||||
|
@ -407,7 +409,8 @@ StickersBox::StickersBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
not_null<ChannelData*> megagroup)
|
not_null<ChannelData*> megagroup)
|
||||||
: _show(std::move(show))
|
: _st(st::stickersRowItem)
|
||||||
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _section(Section::Installed)
|
, _section(Section::Installed)
|
||||||
|
@ -425,7 +428,8 @@ StickersBox::StickersBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
const QVector<MTPStickerSetCovered> &attachedSets)
|
const QVector<MTPStickerSetCovered> &attachedSets)
|
||||||
: _show(std::move(show))
|
: _st(st::stickersRowItem)
|
||||||
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _section(Section::Attached)
|
, _section(Section::Attached)
|
||||||
|
@ -440,7 +444,8 @@ StickersBox::StickersBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
const std::vector<StickerSetIdentifier> &emojiSets)
|
const std::vector<StickerSetIdentifier> &emojiSets)
|
||||||
: _show(std::move(show))
|
: _st(st::stickersRowItem)
|
||||||
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _section(Section::Attached)
|
, _section(Section::Attached)
|
||||||
|
@ -1131,6 +1136,7 @@ StickersBox::Inner::Inner(
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
StickersBox::Section section)
|
StickersBox::Section section)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
|
, _st(st::stickersRowItem)
|
||||||
, _show(std::move(show))
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
|
@ -1150,11 +1156,11 @@ StickersBox::Inner::Inner(
|
||||||
, _inactiveButtonBg(
|
, _inactiveButtonBg(
|
||||||
ImageRoundRadius::Large,
|
ImageRoundRadius::Large,
|
||||||
st::stickersTrendingInstalled.textBg)
|
st::stickersTrendingInstalled.textBg)
|
||||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
, _rowHeight(_st.height)
|
||||||
, _shiftingAnimation([=](crl::time now) {
|
, _shiftingAnimation([=](crl::time now) {
|
||||||
return shiftingAnimationCallback(now);
|
return shiftingAnimationCallback(now);
|
||||||
})
|
})
|
||||||
, _itemsTop(st::membersMarginTop)
|
, _itemsTop(st::lineWidth)
|
||||||
, _addText(tr::lng_stickers_featured_add(tr::now))
|
, _addText(tr::lng_stickers_featured_add(tr::now))
|
||||||
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
|
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
|
||||||
, _undoText(tr::lng_stickers_return(tr::now))
|
, _undoText(tr::lng_stickers_return(tr::now))
|
||||||
|
@ -1169,6 +1175,7 @@ StickersBox::Inner::Inner(
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
not_null<ChannelData*> megagroup)
|
not_null<ChannelData*> megagroup)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
|
, _st(st::stickersRowItem)
|
||||||
, _show(std::move(show))
|
, _show(std::move(show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
|
@ -1188,11 +1195,11 @@ StickersBox::Inner::Inner(
|
||||||
, _inactiveButtonBg(
|
, _inactiveButtonBg(
|
||||||
ImageRoundRadius::Large,
|
ImageRoundRadius::Large,
|
||||||
st::stickersTrendingInstalled.textBg)
|
st::stickersTrendingInstalled.textBg)
|
||||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
, _rowHeight(_st.height)
|
||||||
, _shiftingAnimation([=](crl::time now) {
|
, _shiftingAnimation([=](crl::time now) {
|
||||||
return shiftingAnimationCallback(now);
|
return shiftingAnimationCallback(now);
|
||||||
})
|
})
|
||||||
, _itemsTop(st::membersMarginTop)
|
, _itemsTop(st::lineWidth)
|
||||||
, _megagroupSet(megagroup)
|
, _megagroupSet(megagroup)
|
||||||
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
|
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
|
||||||
, _megagroupSetField(
|
, _megagroupSetField(
|
||||||
|
@ -1328,8 +1335,8 @@ QRect StickersBox::Inner::relativeButtonRect(
|
||||||
buttonh = st.height;
|
buttonh = st.height;
|
||||||
buttonshift = 0;
|
buttonshift = 0;
|
||||||
}
|
}
|
||||||
auto buttonx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - buttonw + buttonshift;
|
auto buttonx = width() - st::contactsPadding.right() - buttonw + buttonshift;
|
||||||
auto buttony = st::contactsPadding.top() + (st::contactsPhotoSize - buttonh) / 2;
|
auto buttony = (_st.height - buttonh) / 2;
|
||||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,7 +1352,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
|
||||||
return -1;
|
return -1;
|
||||||
}();
|
}();
|
||||||
if (index >= 0 && index == selectedIndex) {
|
if (index >= 0 && index == selectedIndex) {
|
||||||
p.fillRect(0, 0, width(), _rowHeight, st::contactsBgOver);
|
p.fillRect(0, 0, width(), _rowHeight, _st.button.textBgOver);
|
||||||
if (row->ripple) {
|
if (row->ripple) {
|
||||||
row->ripple->paint(p, 0, 0, width());
|
row->ripple->paint(p, 0, 0, width());
|
||||||
}
|
}
|
||||||
|
@ -1362,7 +1369,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
|
||||||
current = reachedOpacity;
|
current = reachedOpacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto rect = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2));
|
auto rect = myrtlrect(_st.photoPosition.x() / 2, _st.photoPosition.y() / 2, width() - _st.photoPosition.x() - _scrollbar, _rowHeight - _st.photoPosition.y());
|
||||||
p.setOpacity(current);
|
p.setOpacity(current);
|
||||||
Ui::Shadow::paint(p, rect, width(), st::boxRoundShadow);
|
Ui::Shadow::paint(p, rect, width(), st::boxRoundShadow);
|
||||||
p.setOpacity(1);
|
p.setOpacity(1);
|
||||||
|
@ -1383,27 +1390,27 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
|
||||||
p.setOpacity(st::stickersRowDisabledOpacity);
|
p.setOpacity(st::stickersRowDisabledOpacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stickerx = st::contactsPadding.left();
|
auto stickerskip = 0;
|
||||||
|
|
||||||
if (!_megagroupSet && _isInstalledTab) {
|
if (!_megagroupSet && _isInstalledTab) {
|
||||||
stickerx += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
stickerskip += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||||
if (!row->isRecentSet()) {
|
if (!row->isRecentSet()) {
|
||||||
st::stickersReorderIcon.paint(p, st::contactsPadding.left(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
|
st::stickersReorderIcon.paint(p, _st.photoPosition.x(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row->sticker) {
|
if (row->sticker) {
|
||||||
paintRowThumbnail(p, row, stickerx);
|
paintRowThumbnail(p, row, stickerskip + _st.photoPosition.x());
|
||||||
}
|
}
|
||||||
|
|
||||||
int namex = stickerx + st::contactsPhotoSize + st::contactsPadding.left();
|
int namex = stickerskip + _st.namePosition.x();
|
||||||
int namey = st::contactsPadding.top() + st::contactsNameTop;
|
int namey = _st.namePosition.y();
|
||||||
|
|
||||||
int statusx = namex;
|
int statusx = stickerskip + _st.statusPosition.x();
|
||||||
int statusy = st::contactsPadding.top() + st::contactsStatusTop;
|
int statusy = _st.statusPosition.y();
|
||||||
|
|
||||||
p.setFont(st::contactsNameStyle.font);
|
p.setFont(st::contactsNameStyle.font);
|
||||||
p.setPen(st::contactsNameFg);
|
p.setPen(_st.nameFg);
|
||||||
p.drawTextLeft(namex, namey, width(), row->title, row->titleWidth);
|
p.drawTextLeft(namex, namey, width(), row->title, row->titleWidth);
|
||||||
|
|
||||||
if (row->isUnread()) {
|
if (row->isUnread()) {
|
||||||
|
@ -1425,7 +1432,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
|
||||||
: tr::lng_stickers_count(tr::now, lt_count, row->count);
|
: tr::lng_stickers_count(tr::now, lt_count, row->count);
|
||||||
|
|
||||||
p.setFont(st::contactsStatusFont);
|
p.setFont(st::contactsStatusFont);
|
||||||
p.setPen(st::contactsStatusFg);
|
p.setPen(_st.statusFg);
|
||||||
p.drawTextLeft(statusx, statusy, width(), statusText);
|
p.drawTextLeft(statusx, statusy, width(), statusText);
|
||||||
|
|
||||||
p.setOpacity(1);
|
p.setOpacity(1);
|
||||||
|
@ -1457,15 +1464,15 @@ void StickersBox::Inner::paintRowThumbnail(
|
||||||
? row->stickerMedia->thumbnail()
|
? row->stickerMedia->thumbnail()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto paused = _show->paused(ChatHelpers::PauseReason::Layer);
|
const auto paused = _show->paused(ChatHelpers::PauseReason::Layer);
|
||||||
const auto x = left + (st::contactsPhotoSize - row->pixw) / 2;
|
const auto x = left + (_st.photoSize - row->pixw) / 2;
|
||||||
const auto y = st::contactsPadding.top() + (st::contactsPhotoSize - row->pixh) / 2;
|
const auto y = _st.photoPosition.y() + (_st.photoSize - row->pixh) / 2;
|
||||||
if (row->lottie && row->lottie->ready()) {
|
if (row->lottie && row->lottie->ready()) {
|
||||||
const auto frame = row->lottie->frame();
|
const auto frame = row->lottie->frame();
|
||||||
const auto size = frame.size() / cIntRetinaFactor();
|
const auto size = frame.size() / cIntRetinaFactor();
|
||||||
p.drawImage(
|
p.drawImage(
|
||||||
QRect(
|
QRect(
|
||||||
left + (st::contactsPhotoSize - size.width()) / 2,
|
left + (_st.photoSize - size.width()) / 2,
|
||||||
st::contactsPadding.top() + (st::contactsPhotoSize - size.height()) / 2,
|
_st.photoPosition.y() + (_st.photoSize - size.height()) / 2,
|
||||||
size.width(),
|
size.width(),
|
||||||
size.height()),
|
size.height()),
|
||||||
frame);
|
frame);
|
||||||
|
@ -1500,9 +1507,7 @@ void StickersBox::Inner::validateLottieAnimation(not_null<Row*> row) {
|
||||||
row->thumbnailMedia.get(),
|
row->thumbnailMedia.get(),
|
||||||
row->stickerMedia.get(),
|
row->stickerMedia.get(),
|
||||||
ChatHelpers::StickerLottieSize::SetsListThumbnail,
|
ChatHelpers::StickerLottieSize::SetsListThumbnail,
|
||||||
QSize(
|
QSize(_st.photoSize, _st.photoSize) * cIntRetinaFactor());
|
||||||
st::contactsPhotoSize,
|
|
||||||
st::contactsPhotoSize) * cIntRetinaFactor());
|
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1572,15 +1577,12 @@ void StickersBox::Inner::updateRowThumbnail(not_null<Row*> row) {
|
||||||
}
|
}
|
||||||
Unexpected("StickersBox::Inner::updateRowThumbnail: row not found");
|
Unexpected("StickersBox::Inner::updateRowThumbnail: row not found");
|
||||||
}();
|
}();
|
||||||
const auto left = st::contactsPadding.left()
|
const auto left = _st.photoPosition.x()
|
||||||
+ ((!_megagroupSet && _isInstalledTab)
|
+ ((!_megagroupSet && _isInstalledTab)
|
||||||
? st::stickersReorderIcon.width() + st::stickersReorderSkip
|
? st::stickersReorderIcon.width() + st::stickersReorderSkip
|
||||||
: 0);
|
: 0);
|
||||||
update(
|
const auto top = rowTop + _st.photoPosition.y();
|
||||||
left,
|
update(left, top, _st.photoSize, _st.photoSize);
|
||||||
rowTop + st::contactsPadding.top(),
|
|
||||||
st::contactsPhotoSize,
|
|
||||||
st::contactsPhotoSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int index) {
|
void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int index) {
|
||||||
|
@ -1818,7 +1820,7 @@ void StickersBox::Inner::updateSelected() {
|
||||||
actionSel = -1;
|
actionSel = -1;
|
||||||
}
|
}
|
||||||
if (!_megagroupSet && _isInstalledTab && !row->isRecentSet()) {
|
if (!_megagroupSet && _isInstalledTab && !row->isRecentSet()) {
|
||||||
auto dragAreaWidth = st::contactsPadding.left() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
auto dragAreaWidth = _st.photoPosition.x() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||||
auto dragArea = myrtlrect(0, 0, dragAreaWidth, _rowHeight);
|
auto dragArea = myrtlrect(0, 0, dragAreaWidth, _rowHeight);
|
||||||
inDragArea = dragArea.contains(local);
|
inDragArea = dragArea.contains(local);
|
||||||
}
|
}
|
||||||
|
@ -2142,7 +2144,7 @@ void StickersBox::Inner::rebuildMegagroupSet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::rebuild(bool masks) {
|
void StickersBox::Inner::rebuild(bool masks) {
|
||||||
_itemsTop = st::membersMarginTop;
|
_itemsTop = st::lineWidth;
|
||||||
|
|
||||||
if (_megagroupSet) {
|
if (_megagroupSet) {
|
||||||
_itemsTop += st::groupStickersFieldPadding.top() + _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
_itemsTop += st::groupStickersFieldPadding.top() + _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||||
|
@ -2291,11 +2293,11 @@ bool StickersBox::Inner::skipPremium() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int StickersBox::Inner::countMaxNameWidth(bool installedSet) const {
|
int StickersBox::Inner::countMaxNameWidth(bool installedSet) const {
|
||||||
int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
int namex = _st.namePosition.x();
|
||||||
if (!_megagroupSet && _isInstalledTab) {
|
if (!_megagroupSet && _isInstalledTab) {
|
||||||
namex += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
namex += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||||
}
|
}
|
||||||
int namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x();
|
int namew = st::boxWideWidth - namex - st::contactsPadding.right();
|
||||||
if (_isInstalledTab) {
|
if (_isInstalledTab) {
|
||||||
if (!_megagroupSet) {
|
if (!_megagroupSet) {
|
||||||
namew -= _undoWidth - st::stickersUndoRemove.width;
|
namew -= _undoWidth - st::stickersUndoRemove.width;
|
||||||
|
@ -2401,17 +2403,17 @@ void StickersBox::Inner::fillSetCover(
|
||||||
: QSize(1, 1);
|
: QSize(1, 1);
|
||||||
auto pixw = size.width();
|
auto pixw = size.width();
|
||||||
auto pixh = size.height();
|
auto pixh = size.height();
|
||||||
if (pixw > st::contactsPhotoSize) {
|
if (pixw > _st.photoSize) {
|
||||||
if (pixw > pixh) {
|
if (pixw > pixh) {
|
||||||
pixh = (pixh * st::contactsPhotoSize) / pixw;
|
pixh = (pixh * _st.photoSize) / pixw;
|
||||||
pixw = st::contactsPhotoSize;
|
pixw = _st.photoSize;
|
||||||
} else {
|
} else {
|
||||||
pixw = (pixw * st::contactsPhotoSize) / pixh;
|
pixw = (pixw * _st.photoSize) / pixh;
|
||||||
pixh = st::contactsPhotoSize;
|
pixh = _st.photoSize;
|
||||||
}
|
}
|
||||||
} else if (pixh > st::contactsPhotoSize) {
|
} else if (pixh > _st.photoSize) {
|
||||||
pixw = (pixw * st::contactsPhotoSize) / pixh;
|
pixw = (pixw * _st.photoSize) / pixh;
|
||||||
pixh = st::contactsPhotoSize;
|
pixh = _st.photoSize;
|
||||||
}
|
}
|
||||||
*outWidth = pixw;
|
*outWidth = pixw;
|
||||||
*outHeight = pixh;
|
*outHeight = pixh;
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct RippleAnimation;
|
struct RippleAnimation;
|
||||||
|
struct PeerListItem;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -142,6 +143,7 @@ private:
|
||||||
|
|
||||||
std::array<Inner*, 5> widgets() const;
|
std::array<Inner*, 5> widgets() const;
|
||||||
|
|
||||||
|
const style::PeerListItem &_st;
|
||||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
|
|
@ -95,6 +95,7 @@ Panel::Panel(not_null<Call*> call)
|
||||||
_decline->entity()->setText(tr::lng_call_decline());
|
_decline->entity()->setText(tr::lng_call_decline());
|
||||||
_cancel->setDuration(st::callPanelDuration);
|
_cancel->setDuration(st::callPanelDuration);
|
||||||
_cancel->entity()->setText(tr::lng_call_cancel());
|
_cancel->entity()->setText(tr::lng_call_cancel());
|
||||||
|
_screencast->setDuration(st::callPanelDuration);
|
||||||
|
|
||||||
initWindow();
|
initWindow();
|
||||||
initWidget();
|
initWidget();
|
||||||
|
@ -299,6 +300,7 @@ void Panel::initControls() {
|
||||||
|
|
||||||
_decline->finishAnimating();
|
_decline->finishAnimating();
|
||||||
_cancel->finishAnimating();
|
_cancel->finishAnimating();
|
||||||
|
_screencast->finishAnimating();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::setIncomingSize(QSize size) {
|
void Panel::setIncomingSize(QSize size) {
|
||||||
|
@ -595,6 +597,7 @@ void Panel::showControls() {
|
||||||
widget()->showChildren();
|
widget()->showChildren();
|
||||||
_decline->setVisible(_decline->toggled());
|
_decline->setVisible(_decline->toggled());
|
||||||
_cancel->setVisible(_cancel->toggled());
|
_cancel->setVisible(_cancel->toggled());
|
||||||
|
_screencast->setVisible(_screencast->toggled());
|
||||||
|
|
||||||
const auto shown = !_incomingFrameSize.isEmpty();
|
const auto shown = !_incomingFrameSize.isEmpty();
|
||||||
_incoming->widget()->setVisible(shown);
|
_incoming->widget()->setVisible(shown);
|
||||||
|
@ -753,12 +756,6 @@ void Panel::updateControlsGeometry() {
|
||||||
updateOutgoingVideoBubbleGeometry();
|
updateOutgoingVideoBubbleGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto threeWidth = _answerHangupRedial->width()
|
|
||||||
+ st::callCancel.button.width
|
|
||||||
- _screencast->width();
|
|
||||||
_decline->moveToLeft((widget()->width() - threeWidth) / 2, _buttonsTop);
|
|
||||||
_cancel->moveToLeft((widget()->width() - threeWidth) / 2, _buttonsTop);
|
|
||||||
|
|
||||||
updateHangupGeometry();
|
updateHangupGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,22 +776,28 @@ void Panel::updateOutgoingVideoBubbleGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::updateHangupGeometry() {
|
void Panel::updateHangupGeometry() {
|
||||||
auto twoWidth = _answerHangupRedial->width() + _screencast->width();
|
const auto isWaitingUser = (_call
|
||||||
auto threeWidth = twoWidth + st::callCancel.button.width;
|
&& _call->state() == State::WaitingUserConfirmation);
|
||||||
auto rightFrom = (widget()->width() - threeWidth) / 2;
|
const auto hangupProgress = isWaitingUser
|
||||||
auto rightTo = (widget()->width() - twoWidth) / 2;
|
|
||||||
auto hangupProgress = (_call
|
|
||||||
&& _call->state() == State::WaitingUserConfirmation)
|
|
||||||
? 0.
|
? 0.
|
||||||
: _hangupShownProgress.value(_hangupShown ? 1. : 0.);
|
: _hangupShownProgress.value(_hangupShown ? 1. : 0.);
|
||||||
auto hangupRight = anim::interpolate(rightFrom, rightTo, hangupProgress);
|
|
||||||
_answerHangupRedial->moveToRight(hangupRight, _buttonsTop);
|
|
||||||
_answerHangupRedial->setProgress(hangupProgress);
|
_answerHangupRedial->setProgress(hangupProgress);
|
||||||
_mute->moveToRight(hangupRight - _mute->width(), _buttonsTop);
|
|
||||||
_screencast->moveToLeft(hangupRight - _mute->width(), _buttonsTop);
|
// Screencast - Camera - Cancel/Decline - Answer/Hangup/Redial - Mute.
|
||||||
_camera->moveToLeft(
|
const auto buttonWidth = st::callCancel.button.width;
|
||||||
hangupRight - _mute->width() + _screencast->width(),
|
const auto cancelWidth = buttonWidth * (1. - hangupProgress);
|
||||||
_buttonsTop);
|
const auto cancelLeft = (isWaitingUser)
|
||||||
|
? ((widget()->width() - buttonWidth) / 2)
|
||||||
|
: (_mute->animating())
|
||||||
|
? ((widget()->width() - cancelWidth) / 2)
|
||||||
|
: ((widget()->width() / 2) - cancelWidth);
|
||||||
|
|
||||||
|
_cancel->moveToLeft(cancelLeft, _buttonsTop);
|
||||||
|
_decline->moveToLeft(cancelLeft, _buttonsTop);
|
||||||
|
_camera->moveToLeft(cancelLeft - buttonWidth, _buttonsTop);
|
||||||
|
_screencast->moveToLeft(_camera->x() - buttonWidth, _buttonsTop);
|
||||||
|
_answerHangupRedial->moveToLeft(cancelLeft + cancelWidth, _buttonsTop);
|
||||||
|
_mute->moveToLeft(_answerHangupRedial->x() + buttonWidth, _buttonsTop);
|
||||||
if (_startVideo) {
|
if (_startVideo) {
|
||||||
_startVideo->moveToLeft(_camera->x(), _camera->y());
|
_startVideo->moveToLeft(_camera->x(), _camera->y());
|
||||||
}
|
}
|
||||||
|
@ -877,7 +880,9 @@ void Panel::stateChanged(State state) {
|
||||||
toggleButton(_decline, incomingWaiting);
|
toggleButton(_decline, incomingWaiting);
|
||||||
toggleButton(_cancel, (isBusy || isWaitingUser));
|
toggleButton(_cancel, (isBusy || isWaitingUser));
|
||||||
toggleButton(_mute, !isWaitingUser);
|
toggleButton(_mute, !isWaitingUser);
|
||||||
toggleButton(_screencast, !isWaitingUser);
|
toggleButton(
|
||||||
|
_screencast,
|
||||||
|
!(isBusy || isWaitingUser || incomingWaiting));
|
||||||
const auto hangupShown = !_decline->toggled()
|
const auto hangupShown = !_decline->toggled()
|
||||||
&& !_cancel->toggled();
|
&& !_cancel->toggled();
|
||||||
if (_hangupShown != hangupShown) {
|
if (_hangupShown != hangupShown) {
|
||||||
|
|
|
@ -313,10 +313,26 @@ stickersUndoRemove: RoundButton(defaultLightButton) {
|
||||||
}
|
}
|
||||||
stickersRemoveSkip: 4px;
|
stickersRemoveSkip: 4px;
|
||||||
stickersReorderIcon: icon {{ "stickers_reorder", menuIconFg }};
|
stickersReorderIcon: icon {{ "stickers_reorder", menuIconFg }};
|
||||||
stickersReorderSkip: 13px;
|
stickersReorderSkip: 18px;
|
||||||
|
|
||||||
stickersTabs: defaultTabsSlider;
|
stickersTabs: defaultTabsSlider;
|
||||||
|
|
||||||
|
stickersRowItem: PeerListItem(defaultPeerListItem) {
|
||||||
|
height: 52px;
|
||||||
|
photoSize: 32px;
|
||||||
|
photoPosition: point(18px, 10px);
|
||||||
|
namePosition: point(66px, 7px);
|
||||||
|
statusPosition: point(66px, 26px);
|
||||||
|
button: OutlineButton(defaultPeerListButton) {
|
||||||
|
textBg: contactsBg;
|
||||||
|
textBgOver: contactsBgOver;
|
||||||
|
ripple: defaultRippleAnimation;
|
||||||
|
}
|
||||||
|
statusFg: contactsStatusFg;
|
||||||
|
statusFgOver: contactsStatusFgOver;
|
||||||
|
statusFgActive: contactsStatusFgOnline;
|
||||||
|
}
|
||||||
|
|
||||||
stickerEmojiSkip: 5px;
|
stickerEmojiSkip: 5px;
|
||||||
|
|
||||||
stickersFeaturedBadgeFont: font(12px bold);
|
stickersFeaturedBadgeFont: font(12px bold);
|
||||||
|
@ -351,11 +367,7 @@ filtersRemove: IconButton(stickersRemove) {
|
||||||
|
|
||||||
emojiPanMargins: margins(10px, 10px, 10px, 10px);
|
emojiPanMargins: margins(10px, 10px, 10px, 10px);
|
||||||
|
|
||||||
emojiTabs: SettingsSlider(defaultTabsSlider) {
|
emojiTabs: defaultTabsSlider;
|
||||||
height: 43px;
|
|
||||||
barTop: 40px;
|
|
||||||
labelTop: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
emojiCategoryIconTop: 6px;
|
emojiCategoryIconTop: 6px;
|
||||||
emojiPanAnimation: PanelAnimation(defaultPanelAnimation) {
|
emojiPanAnimation: PanelAnimation(defaultPanelAnimation) {
|
||||||
|
@ -508,6 +520,7 @@ sendBoxAlbumGroupSkipRight: 5px;
|
||||||
sendBoxAlbumGroupSkipTop: 5px;
|
sendBoxAlbumGroupSkipTop: 5px;
|
||||||
sendBoxAlbumGroupRadius: 4px;
|
sendBoxAlbumGroupRadius: 4px;
|
||||||
sendBoxAlbumGroupSize: size(62px, 25px);
|
sendBoxAlbumGroupSize: size(62px, 25px);
|
||||||
|
sendBoxAlbumGroupSizeVertical: size(30px, 50px);
|
||||||
sendBoxAlbumSmallGroupSize: size(30px, 25px);
|
sendBoxAlbumSmallGroupSize: size(30px, 25px);
|
||||||
|
|
||||||
sendBoxFileGroupSkipTop: 2px;
|
sendBoxFileGroupSkipTop: 2px;
|
||||||
|
|
|
@ -123,7 +123,7 @@ void SetCrashAnnotationsGL() {
|
||||||
case Ui::GL::ANGLE::D3D11: return "Direct3D 11";
|
case Ui::GL::ANGLE::D3D11: return "Direct3D 11";
|
||||||
case Ui::GL::ANGLE::D3D9: return "Direct3D 9";
|
case Ui::GL::ANGLE::D3D9: return "Direct3D 9";
|
||||||
case Ui::GL::ANGLE::D3D11on12: return "D3D11on12";
|
case Ui::GL::ANGLE::D3D11on12: return "D3D11on12";
|
||||||
case Ui::GL::ANGLE::OpenGL: return "OpenGL";
|
//case Ui::GL::ANGLE::OpenGL: return "OpenGL";
|
||||||
}
|
}
|
||||||
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
|
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
|
||||||
}());
|
}());
|
||||||
|
|
|
@ -125,7 +125,15 @@ std::map<int, const char*> BetaLogs() {
|
||||||
"- Fix several possible crashes.\n"
|
"- Fix several possible crashes.\n"
|
||||||
|
|
||||||
"- Deprecate macOS 10.12, Ubuntu 18.04 and CentOS 7 in July.\n"
|
"- Deprecate macOS 10.12, Ubuntu 18.04 and CentOS 7 in July.\n"
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
4008011,
|
||||||
|
"- Fix initial video playback speed.\n"
|
||||||
|
|
||||||
|
"- Use native window resize on Windows 11.\n"
|
||||||
|
|
||||||
|
"- Fix memory leak in Direct3D 11 media viewer on Windows.\n"
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
|
||||||
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
|
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
|
||||||
constexpr auto AppName = "AyuGram Desktop"_cs;
|
constexpr auto AppName = "AyuGram Desktop"_cs;
|
||||||
constexpr auto AppFile = "AyuGram"_cs;
|
constexpr auto AppFile = "AyuGram"_cs;
|
||||||
constexpr auto AppVersion = 4008010;
|
constexpr auto AppVersion = 4008011;
|
||||||
constexpr auto AppVersionStr = "4.8.10";
|
constexpr auto AppVersionStr = "4.8.11";
|
||||||
constexpr auto AppBetaVersion = false;
|
constexpr auto AppBetaVersion = true;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
|
|
|
@ -467,16 +467,17 @@ HistoryItem *ScheduledMessages::append(
|
||||||
// probably this message was edited.
|
// probably this message was edited.
|
||||||
if (data.is_edit_hide()) {
|
if (data.is_edit_hide()) {
|
||||||
existing->applyEdition(HistoryMessageEdition(_session, data));
|
existing->applyEdition(HistoryMessageEdition(_session, data));
|
||||||
|
} else {
|
||||||
|
existing->updateSentContent({
|
||||||
|
qs(data.vmessage()),
|
||||||
|
Api::EntitiesFromMTP(
|
||||||
|
_session,
|
||||||
|
data.ventities().value_or_empty())
|
||||||
|
}, data.vmedia());
|
||||||
|
existing->updateReplyMarkup(
|
||||||
|
HistoryMessageMarkupData(data.vreply_markup()));
|
||||||
|
existing->updateForwardedInfo(data.vfwd_from());
|
||||||
}
|
}
|
||||||
existing->updateSentContent({
|
|
||||||
qs(data.vmessage()),
|
|
||||||
Api::EntitiesFromMTP(
|
|
||||||
_session,
|
|
||||||
data.ventities().value_or_empty())
|
|
||||||
}, data.vmedia());
|
|
||||||
existing->updateReplyMarkup(
|
|
||||||
HistoryMessageMarkupData(data.vreply_markup()));
|
|
||||||
existing->updateForwardedInfo(data.vfwd_from());
|
|
||||||
existing->updateDate(data.vdate().v);
|
existing->updateDate(data.vdate().v);
|
||||||
history->owner().requestItemTextRefresh(existing);
|
history->owner().requestItemTextRefresh(existing);
|
||||||
}, [&](const auto &data) {});
|
}, [&](const auto &data) {});
|
||||||
|
|
|
@ -18,6 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavutil/opt.h>
|
#include <libavutil/opt.h>
|
||||||
|
#if !defined DESKTOP_APP_USE_PACKAGED && !defined Q_OS_WIN && !defined Q_OS_MAC
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif // !DESKTOP_APP_USE_PACKAGED && !Q_OS_WIN && !Q_OS_MAC
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
namespace FFmpeg {
|
namespace FFmpeg {
|
||||||
|
@ -85,6 +88,47 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
|
||||||
#endif // LIB_FFMPEG_USE_QT_PRIVATE_API
|
#endif // LIB_FFMPEG_USE_QT_PRIVATE_API
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined DESKTOP_APP_USE_PACKAGED && !defined Q_OS_WIN && !defined Q_OS_MAC
|
||||||
|
[[nodiscard]] auto CheckHwLibs() {
|
||||||
|
auto list = std::deque{
|
||||||
|
AV_PIX_FMT_CUDA,
|
||||||
|
};
|
||||||
|
const auto vdpau = [&] {
|
||||||
|
if (const auto handle = dlopen("libvdpau.so.1", RTLD_LAZY)) {
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
if (dlerror()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
if (vdpau) {
|
||||||
|
list.push_front(AV_PIX_FMT_VDPAU);
|
||||||
|
}
|
||||||
|
const auto va = [&] {
|
||||||
|
const auto list = std::array{
|
||||||
|
"libva-drm.so.1",
|
||||||
|
"libva-x11.so.1",
|
||||||
|
"libva.so.1",
|
||||||
|
"libdrm.so.2",
|
||||||
|
};
|
||||||
|
for (const auto lib : list) {
|
||||||
|
if (const auto handle = dlopen(lib, RTLD_LAZY)) {
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
if (dlerror()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
if (va) {
|
||||||
|
list.push_front(AV_PIX_FMT_VAAPI);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
#endif // !DESKTOP_APP_USE_PACKAGED && !Q_OS_WIN && !Q_OS_MAC
|
||||||
|
|
||||||
[[nodiscard]] bool InitHw(AVCodecContext *context, AVHWDeviceType type) {
|
[[nodiscard]] bool InitHw(AVCodecContext *context, AVHWDeviceType type) {
|
||||||
AVCodecContext *parent = static_cast<AVCodecContext*>(context->opaque);
|
AVCodecContext *parent = static_cast<AVCodecContext*>(context->opaque);
|
||||||
|
|
||||||
|
@ -125,6 +169,9 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
#if !defined DESKTOP_APP_USE_PACKAGED && !defined Q_OS_WIN && !defined Q_OS_MAC
|
||||||
|
static const auto list = CheckHwLibs();
|
||||||
|
#else // !DESKTOP_APP_USE_PACKAGED && !Q_OS_WIN && !Q_OS_MAC
|
||||||
const auto list = std::array{
|
const auto list = std::array{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
AV_PIX_FMT_D3D11,
|
AV_PIX_FMT_D3D11,
|
||||||
|
@ -138,6 +185,7 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
|
||||||
AV_PIX_FMT_CUDA,
|
AV_PIX_FMT_CUDA,
|
||||||
#endif // Q_OS_WIN || Q_OS_MAC
|
#endif // Q_OS_WIN || Q_OS_MAC
|
||||||
};
|
};
|
||||||
|
#endif // DESKTOP_APP_USE_PACKAGED || Q_OS_WIN || Q_OS_MAC
|
||||||
for (const auto format : list) {
|
for (const auto format : list) {
|
||||||
if (!has(format)) {
|
if (!has(format)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1469,6 +1469,12 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
const auto updatingSavedLocalEdit = !edition.savePreviousMedia
|
||||||
|
&& (_savedLocalEditMediaData != nullptr);
|
||||||
|
if (!_savedLocalEditMediaData && edition.savePreviousMedia) {
|
||||||
|
savePreviousMedia();
|
||||||
|
}
|
||||||
|
|
||||||
if (edition.isEditHide) {
|
if (edition.isEditHide) {
|
||||||
_flags |= MessageFlag::HideEdited;
|
_flags |= MessageFlag::HideEdited;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1488,8 +1494,14 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
|
||||||
setReplyMarkup(base::take(edition.replyMarkup));
|
setReplyMarkup(base::take(edition.replyMarkup));
|
||||||
}
|
}
|
||||||
if (!isLocalUpdateMedia()) {
|
if (!isLocalUpdateMedia()) {
|
||||||
removeFromSharedMediaIndex();
|
if (updatingSavedLocalEdit) {
|
||||||
refreshMedia(edition.mtpMedia);
|
_savedLocalEditMediaData->media = edition.mtpMedia
|
||||||
|
? CreateMedia(this, *edition.mtpMedia)
|
||||||
|
: nullptr;
|
||||||
|
} else {
|
||||||
|
removeFromSharedMediaIndex();
|
||||||
|
refreshMedia(edition.mtpMedia);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!edition.useSameReactions) {
|
if (!edition.useSameReactions) {
|
||||||
updateReactions(edition.mtpReactions);
|
updateReactions(edition.mtpReactions);
|
||||||
|
@ -1500,10 +1512,18 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
|
||||||
if (!edition.useSameForwards) {
|
if (!edition.useSameForwards) {
|
||||||
setForwardsCount(edition.forwards);
|
setForwardsCount(edition.forwards);
|
||||||
}
|
}
|
||||||
setText(_media
|
const auto &checkedMedia = updatingSavedLocalEdit
|
||||||
|
? _savedLocalEditMediaData->media
|
||||||
|
: _media;
|
||||||
|
auto updatedText = checkedMedia
|
||||||
? edition.textWithEntities
|
? edition.textWithEntities
|
||||||
: EnsureNonEmpty(edition.textWithEntities));
|
: EnsureNonEmpty(edition.textWithEntities);
|
||||||
if (!isLocalUpdateMedia()) {
|
if (updatingSavedLocalEdit) {
|
||||||
|
_savedLocalEditMediaData->text = std::move(updatedText);
|
||||||
|
} else {
|
||||||
|
setText(std::move(updatedText));
|
||||||
|
}
|
||||||
|
if (!isLocalUpdateMedia() && !updatingSavedLocalEdit) {
|
||||||
indexAsNewItem();
|
indexAsNewItem();
|
||||||
}
|
}
|
||||||
if (!edition.useSameReplies) {
|
if (!edition.useSameReplies) {
|
||||||
|
@ -1652,6 +1672,9 @@ void HistoryItem::applySentMessage(
|
||||||
void HistoryItem::updateSentContent(
|
void HistoryItem::updateSentContent(
|
||||||
const TextWithEntities &textWithEntities,
|
const TextWithEntities &textWithEntities,
|
||||||
const MTPMessageMedia *media) {
|
const MTPMessageMedia *media) {
|
||||||
|
if (_savedLocalEditMediaData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setText(textWithEntities);
|
setText(textWithEntities);
|
||||||
if (_flags & MessageFlag::FromInlineBot) {
|
if (_flags & MessageFlag::FromInlineBot) {
|
||||||
if (!media || !_media || !_media->updateInlineResultMedia(*media)) {
|
if (!media || !_media || !_media->updateInlineResultMedia(*media)) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct HistoryMessageEdition {
|
||||||
bool useSameReplies = false;
|
bool useSameReplies = false;
|
||||||
bool useSameMarkup = false;
|
bool useSameMarkup = false;
|
||||||
bool useSameReactions = false;
|
bool useSameReactions = false;
|
||||||
|
bool savePreviousMedia = false;
|
||||||
TextWithEntities textWithEntities;
|
TextWithEntities textWithEntities;
|
||||||
HistoryMessageMarkupData replyMarkup;
|
HistoryMessageMarkupData replyMarkup;
|
||||||
HistoryMessageRepliesData replies;
|
HistoryMessageRepliesData replies;
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct MessageToEdit {
|
||||||
struct VoiceToSend {
|
struct VoiceToSend {
|
||||||
QByteArray bytes;
|
QByteArray bytes;
|
||||||
VoiceWaveform waveform;
|
VoiceWaveform waveform;
|
||||||
int duration = 0;
|
crl::time duration = 0;
|
||||||
Api::SendOptions options;
|
Api::SendOptions options;
|
||||||
};
|
};
|
||||||
struct SendActionUpdate {
|
struct SendActionUpdate {
|
||||||
|
|
|
@ -77,8 +77,8 @@ enum class FilterType {
|
||||||
return std::clamp(float64(low) / high, 0., 1.);
|
return std::clamp(float64(low) / high, 0., 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Duration(int samples) {
|
[[nodiscard]] crl::time Duration(int samples) {
|
||||||
return samples / ::Media::Player::kDefaultFrequency;
|
return samples * crl::time(1000) / ::Media::Player::kDefaultFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto FormatVoiceDuration(int samples) {
|
[[nodiscard]] auto FormatVoiceDuration(int samples) {
|
||||||
|
|
|
@ -55,7 +55,9 @@ namespace {
|
||||||
result.preview = kEmpty;
|
result.preview = kEmpty;
|
||||||
result.spoilerRepaint = nullptr;
|
result.spoilerRepaint = nullptr;
|
||||||
} else {
|
} else {
|
||||||
result.preview = preview->original();
|
result.preview = Images::Round(
|
||||||
|
preview->original(),
|
||||||
|
ImageRoundRadius::Small);
|
||||||
result.spoilerRepaint = spoiler ? repaint : nullptr;
|
result.spoilerRepaint = spoiler ? repaint : nullptr;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -607,7 +607,7 @@ void ScheduledWidget::send(Api::SendOptions options) {
|
||||||
void ScheduledWidget::sendVoice(
|
void ScheduledWidget::sendVoice(
|
||||||
QByteArray bytes,
|
QByteArray bytes,
|
||||||
VoiceWaveform waveform,
|
VoiceWaveform waveform,
|
||||||
int duration) {
|
crl::time duration) {
|
||||||
const auto callback = [=](Api::SendOptions options) {
|
const auto callback = [=](Api::SendOptions options) {
|
||||||
sendVoice(bytes, waveform, duration, options);
|
sendVoice(bytes, waveform, duration, options);
|
||||||
};
|
};
|
||||||
|
@ -617,7 +617,7 @@ void ScheduledWidget::sendVoice(
|
||||||
void ScheduledWidget::sendVoice(
|
void ScheduledWidget::sendVoice(
|
||||||
QByteArray bytes,
|
QByteArray bytes,
|
||||||
VoiceWaveform waveform,
|
VoiceWaveform waveform,
|
||||||
int duration,
|
crl::time duration,
|
||||||
Api::SendOptions options) {
|
Api::SendOptions options) {
|
||||||
session().api().sendVoiceMessage(
|
session().api().sendVoiceMessage(
|
||||||
bytes,
|
bytes,
|
||||||
|
|
|
@ -197,11 +197,14 @@ private:
|
||||||
Api::SendOptions options) const;
|
Api::SendOptions options) const;
|
||||||
void send();
|
void send();
|
||||||
void send(Api::SendOptions options);
|
void send(Api::SendOptions options);
|
||||||
void sendVoice(QByteArray bytes, VoiceWaveform waveform, int duration);
|
|
||||||
void sendVoice(
|
void sendVoice(
|
||||||
QByteArray bytes,
|
QByteArray bytes,
|
||||||
VoiceWaveform waveform,
|
VoiceWaveform waveform,
|
||||||
int duration,
|
crl::time duration);
|
||||||
|
void sendVoice(
|
||||||
|
QByteArray bytes,
|
||||||
|
VoiceWaveform waveform,
|
||||||
|
crl::time duration,
|
||||||
Api::SendOptions options);
|
Api::SendOptions options);
|
||||||
void edit(
|
void edit(
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
|
|
|
@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unique_qptr.h"
|
#include "base/unique_qptr.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SettingsSlider;
|
|
||||||
class VerticalLayout;
|
class VerticalLayout;
|
||||||
class SearchFieldController;
|
class SearchFieldController;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -10,10 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <rpl/event_stream.h>
|
#include <rpl/event_stream.h>
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class SettingsSlider;
|
|
||||||
} // namespace Ui
|
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class ConnectionState;
|
class ConnectionState;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
|
@ -15,7 +15,6 @@ enum class SharedMediaType : signed char;
|
||||||
} // namespace Storage
|
} // namespace Storage
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SettingsSlider;
|
|
||||||
class FadeShadow;
|
class FadeShadow;
|
||||||
class PlainShadow;
|
class PlainShadow;
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
|
|
|
@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/media/info_media_list_widget.h"
|
#include "info/media/info_media_list_widget.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SettingsSlider;
|
|
||||||
class VerticalLayout;
|
class VerticalLayout;
|
||||||
class SearchFieldController;
|
class SearchFieldController;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unique_qptr.h"
|
#include "base/unique_qptr.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SettingsSlider;
|
|
||||||
class VerticalLayout;
|
class VerticalLayout;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/sandbox.h"
|
#include "core/sandbox.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "export/export_manager.h"
|
#include "export/export_manager.h"
|
||||||
|
#include "inline_bots/bot_attach_web_view.h" // AttachWebView::cancel.
|
||||||
#include "intro/intro_widget.h"
|
#include "intro/intro_widget.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "main/main_account.h" // Account::sessionValue.
|
#include "main/main_account.h" // Account::sessionValue.
|
||||||
|
@ -198,6 +199,9 @@ void MainWindow::setupPasscodeLock() {
|
||||||
_passcodeLock->showFinished();
|
_passcodeLock->showFinished();
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
|
if (const auto sessionController = controller().sessionController()) {
|
||||||
|
sessionController->session().attachWebView().cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::clearPasscodeLock() {
|
void MainWindow::clearPasscodeLock() {
|
||||||
|
|
|
@ -1560,7 +1560,7 @@ Ui::PreparedFileInformation PrepareForSending(
|
||||||
FFMpegAttributesReader reader(Core::FileLocation(fname), data);
|
FFMpegAttributesReader reader(Core::FileLocation(fname), data);
|
||||||
const auto positionMs = crl::time(0);
|
const auto positionMs = crl::time(0);
|
||||||
if (reader.open(positionMs) && reader.duration() > 0) {
|
if (reader.open(positionMs) && reader.duration() > 0) {
|
||||||
result.duration = reader.duration() / 1000;
|
result.duration = reader.duration();
|
||||||
result.title = reader.title();
|
result.title = reader.title();
|
||||||
result.performer = reader.performer();
|
result.performer = reader.performer();
|
||||||
result.cover = reader.cover();
|
result.cover = reader.cover();
|
||||||
|
|
|
@ -900,7 +900,7 @@ void OverlayWidget::savePosition() {
|
||||||
|
|
||||||
void OverlayWidget::updateGeometry(bool inMove) {
|
void OverlayWidget::updateGeometry(bool inMove) {
|
||||||
initFullScreen();
|
initFullScreen();
|
||||||
if (_fullscreen) {
|
if (_fullscreen && (!Platform::IsWindows11OrGreater() || !isHidden())) {
|
||||||
updateGeometryToScreen(inMove);
|
updateGeometryToScreen(inMove);
|
||||||
} else if (_windowed && _normalGeometryInited) {
|
} else if (_windowed && _normalGeometryInited) {
|
||||||
_window->setGeometry(_normalGeometry);
|
_window->setGeometry(_normalGeometry);
|
||||||
|
@ -3209,6 +3209,12 @@ void OverlayWidget::show(OpenRequest request) {
|
||||||
// Count top notch on macOS before counting geometry.
|
// Count top notch on macOS before counting geometry.
|
||||||
_helper->beforeShow(_fullscreen);
|
_helper->beforeShow(_fullscreen);
|
||||||
}
|
}
|
||||||
|
if (_cachedShow) {
|
||||||
|
_cachedShow->showOrHideBoxOrLayer(
|
||||||
|
v::null,
|
||||||
|
Ui::LayerOption::CloseOther,
|
||||||
|
anim::type::instant);
|
||||||
|
}
|
||||||
if (photo) {
|
if (photo) {
|
||||||
if (contextItem && contextPeer) {
|
if (contextItem && contextPeer) {
|
||||||
return;
|
return;
|
||||||
|
@ -3529,6 +3535,9 @@ void OverlayWidget::showAndActivate() {
|
||||||
_wasWindowedMode = true;
|
_wasWindowedMode = true;
|
||||||
} else if (_fullscreen) {
|
} else if (_fullscreen) {
|
||||||
_window->showFullScreen();
|
_window->showFullScreen();
|
||||||
|
if (Platform::IsWindows11OrGreater()) {
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_window->showMaximized();
|
_window->showMaximized();
|
||||||
}
|
}
|
||||||
|
@ -4045,8 +4054,8 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
||||||
const auto messageId = _message ? _message->fullId() : FullMsgId();
|
const auto messageId = _message ? _message->fullId() : FullMsgId();
|
||||||
options.audioId = AudioMsgId(_document, messageId);
|
options.audioId = AudioMsgId(_document, messageId);
|
||||||
options.speed = _stories
|
options.speed = _stories
|
||||||
? Core::App().settings().videoPlaybackSpeed()
|
? 1.
|
||||||
: 1.;
|
: Core::App().settings().videoPlaybackSpeed();
|
||||||
if (_pip) {
|
if (_pip) {
|
||||||
_pip = nullptr;
|
_pip = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ QByteArray DnsUserAgent() {
|
||||||
static const auto kResult = QByteArray(
|
static const auto kResult = QByteArray(
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
"Chrome/114.0.5735.133 Safari/537.36");
|
"Chrome/115.0.5790.102 Safari/537.36");
|
||||||
return kResult;
|
return kResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <QtGui/QDesktopServices>
|
#include <QtGui/QDesktopServices>
|
||||||
|
|
||||||
#include <glibmm.h>
|
#include <gio/gio.hpp>
|
||||||
#include <giomm.h>
|
|
||||||
|
using namespace gi::repository;
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace File {
|
namespace File {
|
||||||
|
|
||||||
void UnsafeOpenUrl(const QString &url) {
|
void UnsafeOpenUrl(const QString &url) {
|
||||||
try {
|
{
|
||||||
if (Gio::AppInfo::launch_default_for_uri(
|
const auto result = Gio::AppInfo::launch_default_for_uri(
|
||||||
url.toStdString(),
|
url.toStdString(),
|
||||||
base::Platform::AppLaunchContext())) {
|
base::Platform::AppLaunchContext());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
LOG(("App Error: %1").arg(
|
||||||
|
QString::fromStdString(result.error().what())));
|
||||||
|
} else if (*result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LOG(("App Error: %1").arg(QString::fromStdString(e.what())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
|
@ -45,14 +49,29 @@ bool UnsafeShowOpenWith(const QString &filepath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnsafeLaunch(const QString &filepath) {
|
void UnsafeLaunch(const QString &filepath) {
|
||||||
try {
|
if ([&] {
|
||||||
if (Gio::AppInfo::launch_default_for_uri(
|
const auto filename = GLib::filename_to_uri(filepath.toStdString());
|
||||||
Glib::filename_to_uri(filepath.toStdString()),
|
if (!filename) {
|
||||||
base::Platform::AppLaunchContext())) {
|
LOG(("App Error: %1").arg(
|
||||||
return;
|
QString::fromStdString(filename.error().what())));
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LOG(("App Error: %1").arg(QString::fromStdString(e.what())));
|
const auto result = Gio::AppInfo::launch_default_for_uri(
|
||||||
|
*filename,
|
||||||
|
base::Platform::AppLaunchContext());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
LOG(("App Error: %1").arg(
|
||||||
|
QString::fromStdString(result.error().what())));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result;
|
||||||
|
}()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UnsafeShowOpenWith(filepath)) {
|
if (UnsafeShowOpenWith(filepath)) {
|
||||||
|
|
|
@ -17,79 +17,168 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <QtCore/QAbstractEventDispatcher>
|
#include <QtCore/QAbstractEventDispatcher>
|
||||||
|
|
||||||
|
#include <glibmm.h>
|
||||||
|
#include <gio/gio.hpp>
|
||||||
#include <xdpinhibit/xdpinhibit.hpp>
|
#include <xdpinhibit/xdpinhibit.hpp>
|
||||||
#include <giomm.h>
|
|
||||||
|
|
||||||
typedef GApplication TDesktopApplication;
|
namespace Platform {
|
||||||
typedef GApplicationClass TDesktopApplicationClass;
|
namespace {
|
||||||
|
|
||||||
G_DEFINE_TYPE(
|
using namespace gi::repository;
|
||||||
TDesktopApplication,
|
|
||||||
t_desktop_application,
|
|
||||||
G_TYPE_APPLICATION)
|
|
||||||
|
|
||||||
static void t_desktop_application_class_init(
|
class Application : public Gio::impl::ApplicationImpl {
|
||||||
TDesktopApplicationClass *klass) {
|
public:
|
||||||
const auto application_class = G_APPLICATION_CLASS(klass);
|
Application();
|
||||||
|
|
||||||
application_class->local_command_line = [](
|
void before_emit_(GLib::Variant platformData) noexcept override {
|
||||||
GApplication *application,
|
|
||||||
char ***arguments,
|
|
||||||
int *exit_status) -> gboolean {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
application_class->command_line = [](
|
|
||||||
GApplication *application,
|
|
||||||
GApplicationCommandLine *cmdline) {
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
application_class->before_emit = [](
|
|
||||||
GApplication *application,
|
|
||||||
GVariant *platformData) {
|
|
||||||
if (Platform::IsWayland()) {
|
if (Platform::IsWayland()) {
|
||||||
static const auto keys = {
|
static const auto keys = {
|
||||||
"activation-token",
|
"activation-token",
|
||||||
"desktop-startup-id",
|
"desktop-startup-id",
|
||||||
};
|
};
|
||||||
for (const auto &key : keys) {
|
for (const auto &key : keys) {
|
||||||
const char *token = nullptr;
|
if (auto token = platformData.lookup_value(key)) {
|
||||||
g_variant_lookup(platformData, key, "&s", &token);
|
qputenv(
|
||||||
if (token) {
|
"XDG_ACTIVATION_TOKEN",
|
||||||
qputenv("XDG_ACTIVATION_TOKEN", token);
|
token.get_string(nullptr).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
application_class->add_platform_data = [](
|
void activate_() noexcept override {
|
||||||
GApplication *application,
|
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
||||||
GVariantBuilder *builder) {
|
Core::App().activate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_(GFile **files, int n_files, const char*) noexcept override {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
for (int i = 0; i < n_files; ++i) {
|
||||||
|
QFileOpenEvent e(
|
||||||
|
QUrl(QString::fromUtf8(g_file_get_uri(files[i]))));
|
||||||
|
QGuiApplication::sendEvent(qApp, &e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_platform_data_(GLib::VariantBuilder builder) noexcept override {
|
||||||
if (Platform::IsWayland()) {
|
if (Platform::IsWayland()) {
|
||||||
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
|
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
|
||||||
if (!token.isEmpty()) {
|
if (!token.isEmpty()) {
|
||||||
g_variant_builder_add(
|
builder.add_value(
|
||||||
builder,
|
GLib::Variant::new_dict_entry(
|
||||||
"{sv}",
|
GLib::Variant::new_string("activation-token"),
|
||||||
"activation-token",
|
GLib::Variant::new_variant(
|
||||||
g_variant_new_string(token.constData()));
|
GLib::Variant::new_string(token.toStdString()))));
|
||||||
qunsetenv("XDG_ACTIVATION_TOKEN");
|
qunsetenv("XDG_ACTIVATION_TOKEN");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Application::Application()
|
||||||
|
: Gio::impl::ApplicationImpl(this) {
|
||||||
|
const auto appId = QGuiApplication::desktopFileName().toStdString();
|
||||||
|
if (Gio::Application::id_is_valid(appId)) {
|
||||||
|
set_application_id(appId);
|
||||||
|
}
|
||||||
|
set_flags(Gio::ApplicationFlags::HANDLES_OPEN_);
|
||||||
|
|
||||||
|
auto actionMap = Gio::ActionMap(*this);
|
||||||
|
|
||||||
|
auto quitAction = Gio::SimpleAction::new_("quit");
|
||||||
|
quitAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
||||||
|
Core::Quit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
actionMap.add_action(quitAction);
|
||||||
|
|
||||||
|
using Window::Notifications::Manager;
|
||||||
|
using NotificationId = Manager::NotificationId;
|
||||||
|
using NotificationIdTuple = std::invoke_result_t<
|
||||||
|
decltype(&NotificationId::toTuple),
|
||||||
|
NotificationId*
|
||||||
|
>;
|
||||||
|
|
||||||
|
const auto notificationIdVariantType = [] {
|
||||||
|
try {
|
||||||
|
return gi::wrap(
|
||||||
|
Glib::create_variant(
|
||||||
|
NotificationId().toTuple()
|
||||||
|
).get_type().gobj_copy(),
|
||||||
|
gi::transfer_full,
|
||||||
|
gi::direction_out
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
return GLib::VariantType();
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
auto notificationActivateAction = Gio::SimpleAction::new_(
|
||||||
|
"notification-activate",
|
||||||
|
notificationIdVariantType);
|
||||||
|
|
||||||
|
notificationActivateAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
try {
|
||||||
|
const auto &app = Core::App();
|
||||||
|
app.notifications().manager().notificationActivated(
|
||||||
|
NotificationId::FromTuple(
|
||||||
|
Glib::wrap(
|
||||||
|
parameter.gobj_copy_()
|
||||||
|
).get_dynamic<NotificationIdTuple>()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
actionMap.add_action(notificationActivateAction);
|
||||||
|
|
||||||
|
auto notificationMarkAsReadAction = Gio::SimpleAction::new_(
|
||||||
|
"notification-mark-as-read",
|
||||||
|
notificationIdVariantType);
|
||||||
|
|
||||||
|
notificationMarkAsReadAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
try {
|
||||||
|
const auto &app = Core::App();
|
||||||
|
app.notifications().manager().notificationReplied(
|
||||||
|
NotificationId::FromTuple(
|
||||||
|
Glib::wrap(
|
||||||
|
parameter.gobj_copy_()
|
||||||
|
).get_dynamic<NotificationIdTuple>()
|
||||||
|
),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
actionMap.add_action(notificationMarkAsReadAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void t_desktop_application_init(TDesktopApplication *application) {
|
gi::ref_ptr<Application> MakeApplication() {
|
||||||
|
const auto result = gi::make_ref<Application>();
|
||||||
|
if (const auto registered = result->register_(); !registered) {
|
||||||
|
LOG(("App Error: Failed to register: %1").arg(
|
||||||
|
QString::fromStdString(registered.error().message_())));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Platform {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using namespace gi::repository;
|
|
||||||
namespace Gio = gi::repository::Gio;
|
|
||||||
|
|
||||||
class LinuxIntegration final : public Integration {
|
class LinuxIntegration final : public Integration {
|
||||||
public:
|
public:
|
||||||
LinuxIntegration();
|
LinuxIntegration();
|
||||||
|
@ -103,14 +192,14 @@ private:
|
||||||
|
|
||||||
void initInhibit();
|
void initInhibit();
|
||||||
|
|
||||||
static void LaunchNativeApplication();
|
const gi::ref_ptr<Application> _application;
|
||||||
|
|
||||||
XdpInhibit::InhibitProxy _inhibitProxy;
|
XdpInhibit::InhibitProxy _inhibitProxy;
|
||||||
base::Platform::XDP::SettingWatcher _darkModeWatcher;
|
base::Platform::XDP::SettingWatcher _darkModeWatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
LinuxIntegration::LinuxIntegration()
|
LinuxIntegration::LinuxIntegration()
|
||||||
: _inhibitProxy(
|
: _application(MakeApplication())
|
||||||
|
, _inhibitProxy(
|
||||||
XdpInhibit::InhibitProxy::new_for_bus_sync(
|
XdpInhibit::InhibitProxy::new_for_bus_sync(
|
||||||
Gio::BusType::SESSION_,
|
Gio::BusType::SESSION_,
|
||||||
Gio::DBusProxyFlags::DO_NOT_AUTO_START_AT_CONSTRUCTION_,
|
Gio::DBusProxyFlags::DO_NOT_AUTO_START_AT_CONSTRUCTION_,
|
||||||
|
@ -139,16 +228,12 @@ LinuxIntegration::LinuxIntegration()
|
||||||
if (!QCoreApplication::eventDispatcher()->inherits(
|
if (!QCoreApplication::eventDispatcher()->inherits(
|
||||||
"QEventDispatcherGlib")) {
|
"QEventDispatcherGlib")) {
|
||||||
g_warning("Qt is running without GLib event loop integration, "
|
g_warning("Qt is running without GLib event loop integration, "
|
||||||
"except various functionality to not to work.");
|
"expect various functionality to not to work.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxIntegration::init() {
|
void LinuxIntegration::init() {
|
||||||
initInhibit();
|
initInhibit();
|
||||||
|
|
||||||
Glib::signal_idle().connect_once([] {
|
|
||||||
LaunchNativeApplication();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxIntegration::initInhibit() {
|
void LinuxIntegration::initInhibit() {
|
||||||
|
@ -156,7 +241,11 @@ void LinuxIntegration::initInhibit() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto uniqueName = _inhibitProxy.get_connection().get_unique_name();
|
auto uniqueName = _inhibitProxy
|
||||||
|
.get_connection()
|
||||||
|
.get_unique_name()
|
||||||
|
.value_or("");
|
||||||
|
|
||||||
uniqueName.erase(0, 1);
|
uniqueName.erase(0, 1);
|
||||||
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
|
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
|
||||||
|
|
||||||
|
@ -207,115 +296,6 @@ void LinuxIntegration::initInhibit() {
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxIntegration::LaunchNativeApplication() {
|
|
||||||
const auto appId = QGuiApplication::desktopFileName().toStdString();
|
|
||||||
|
|
||||||
const auto app = Glib::wrap(
|
|
||||||
G_APPLICATION(
|
|
||||||
g_object_new(
|
|
||||||
t_desktop_application_get_type(),
|
|
||||||
"application-id",
|
|
||||||
::Gio::Application::id_is_valid(appId)
|
|
||||||
? appId.c_str()
|
|
||||||
: nullptr,
|
|
||||||
"flags",
|
|
||||||
G_APPLICATION_HANDLES_OPEN,
|
|
||||||
nullptr)));
|
|
||||||
|
|
||||||
app->signal_startup().connect([weak = std::weak_ptr(app)] {
|
|
||||||
const auto app = weak.lock();
|
|
||||||
if (!app) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GNotification
|
|
||||||
InvokeQueued(qApp, [] {
|
|
||||||
Core::App().notifications().createManager();
|
|
||||||
});
|
|
||||||
|
|
||||||
QEventLoop().exec();
|
|
||||||
app->quit();
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->signal_activate().connect([] {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
|
||||||
Core::App().activate();
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->signal_open().connect([](
|
|
||||||
const ::Gio::Application::type_vec_files &files,
|
|
||||||
const Glib::ustring &hint) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
for (const auto &file : files) {
|
|
||||||
QFileOpenEvent e(
|
|
||||||
QUrl(QString::fromStdString(file->get_uri())));
|
|
||||||
QGuiApplication::sendEvent(qApp, &e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->add_action("quit", [] {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
|
||||||
Core::Quit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
using Window::Notifications::Manager;
|
|
||||||
using NotificationId = Manager::NotificationId;
|
|
||||||
using NotificationIdTuple = std::invoke_result_t<
|
|
||||||
decltype(&NotificationId::toTuple),
|
|
||||||
NotificationId*
|
|
||||||
>;
|
|
||||||
|
|
||||||
const auto notificationIdVariantType = [] {
|
|
||||||
try {
|
|
||||||
return Glib::create_variant(
|
|
||||||
NotificationId().toTuple()
|
|
||||||
).get_type();
|
|
||||||
} catch (...) {
|
|
||||||
return Glib::VariantType();
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
app->add_action_with_parameter(
|
|
||||||
"notification-activate",
|
|
||||||
notificationIdVariantType,
|
|
||||||
[](const Glib::VariantBase ¶meter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
try {
|
|
||||||
const auto &app = Core::App();
|
|
||||||
app.notifications().manager().notificationActivated(
|
|
||||||
NotificationId::FromTuple(
|
|
||||||
parameter.get_dynamic<NotificationIdTuple>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app->add_action_with_parameter(
|
|
||||||
"notification-mark-as-read",
|
|
||||||
notificationIdVariantType,
|
|
||||||
[](const Glib::VariantBase ¶meter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
try {
|
|
||||||
const auto &app = Core::App();
|
|
||||||
app.notifications().manager().notificationReplied(
|
|
||||||
NotificationId::FromTuple(
|
|
||||||
parameter.get_dynamic<NotificationIdTuple>()
|
|
||||||
),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app->run(0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Integration> CreateIntegration() {
|
std::unique_ptr<Integration> CreateIntegration() {
|
||||||
|
|
|
@ -360,6 +360,7 @@ private:
|
||||||
|
|
||||||
Glib::RefPtr<Gio::Application> _application;
|
Glib::RefPtr<Gio::Application> _application;
|
||||||
Glib::RefPtr<Gio::Notification> _notification;
|
Glib::RefPtr<Gio::Notification> _notification;
|
||||||
|
const std::string _guid;
|
||||||
|
|
||||||
Glib::RefPtr<Gio::DBus::Connection> _dbusConnection;
|
Glib::RefPtr<Gio::DBus::Connection> _dbusConnection;
|
||||||
Glib::ustring _title;
|
Glib::ustring _title;
|
||||||
|
@ -390,7 +391,8 @@ NotificationData::NotificationData(
|
||||||
, _id(id)
|
, _id(id)
|
||||||
, _application(UseGNotification()
|
, _application(UseGNotification()
|
||||||
? Gio::Application::get_default()
|
? Gio::Application::get_default()
|
||||||
: nullptr) {
|
: nullptr)
|
||||||
|
, _guid(_application ? Gio::DBus::generate_guid() : std::string()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotificationData::init(
|
bool NotificationData::init(
|
||||||
|
@ -623,13 +625,7 @@ NotificationData::~NotificationData() {
|
||||||
|
|
||||||
void NotificationData::show() {
|
void NotificationData::show() {
|
||||||
if (_application && _notification) {
|
if (_application && _notification) {
|
||||||
_application->send_notification(
|
_application->send_notification(_guid, _notification);
|
||||||
std::to_string(_id.contextId.sessionId)
|
|
||||||
+ '-'
|
|
||||||
+ std::to_string(_id.contextId.peerId.value)
|
|
||||||
+ '-'
|
|
||||||
+ std::to_string(_id.msgId.bare),
|
|
||||||
_notification);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,12 +675,7 @@ void NotificationData::show() {
|
||||||
|
|
||||||
void NotificationData::close() {
|
void NotificationData::close() {
|
||||||
if (_application) {
|
if (_application) {
|
||||||
_application->withdraw_notification(
|
_application->withdraw_notification(_guid);
|
||||||
std::to_string(_id.contextId.sessionId)
|
|
||||||
+ '-'
|
|
||||||
+ std::to_string(_id.contextId.peerId.value)
|
|
||||||
+ '-'
|
|
||||||
+ std::to_string(_id.msgId.bare));
|
|
||||||
_manager->clearNotification(_id);
|
_manager->clearNotification(_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,11 +382,18 @@ bool GenerateServiceFile(bool silent = false) {
|
||||||
md5Hash));
|
md5Hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess::execute(u"systemctl"_q, {
|
try {
|
||||||
u"--user"_q,
|
const auto connection = Gio::DBus::Connection::get_sync(
|
||||||
u"reload"_q,
|
Gio::DBus::BusType::SESSION);
|
||||||
u"dbus"_q,
|
|
||||||
});
|
connection->call_sync(
|
||||||
|
base::Platform::DBus::kObjectPath,
|
||||||
|
base::Platform::DBus::kInterface,
|
||||||
|
"ReloadConfig",
|
||||||
|
{},
|
||||||
|
base::Platform::DBus::kService);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,6 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||||
: Window::MainWindow(controller)
|
: Window::MainWindow(controller)
|
||||||
, _private(std::make_unique<Private>(this))
|
, _private(std::make_unique<Private>(this))
|
||||||
, psMainMenu(this) {
|
, psMainMenu(this) {
|
||||||
auto forceOpenGL = std::make_unique<QOpenGLWidget>(this);
|
|
||||||
_hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); });
|
_hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -737,18 +737,19 @@ void SetupANGLE(
|
||||||
tr::lng_settings_angle_backend_d3d11(tr::now),
|
tr::lng_settings_angle_backend_d3d11(tr::now),
|
||||||
tr::lng_settings_angle_backend_d3d9(tr::now),
|
tr::lng_settings_angle_backend_d3d9(tr::now),
|
||||||
tr::lng_settings_angle_backend_d3d11on12(tr::now),
|
tr::lng_settings_angle_backend_d3d11on12(tr::now),
|
||||||
tr::lng_settings_angle_backend_opengl(tr::now),
|
//tr::lng_settings_angle_backend_opengl(tr::now),
|
||||||
tr::lng_settings_angle_backend_disabled(tr::now),
|
tr::lng_settings_angle_backend_disabled(tr::now),
|
||||||
};
|
};
|
||||||
const auto backendIndex = [] {
|
const auto disabled = int(options.size()) - 1;
|
||||||
|
const auto backendIndex = [=] {
|
||||||
if (Core::App().settings().disableOpenGL()) {
|
if (Core::App().settings().disableOpenGL()) {
|
||||||
return 5;
|
return disabled;
|
||||||
} else switch (Ui::GL::CurrentANGLE()) {
|
} else switch (Ui::GL::CurrentANGLE()) {
|
||||||
case ANGLE::Auto: return 0;
|
case ANGLE::Auto: return 0;
|
||||||
case ANGLE::D3D11: return 1;
|
case ANGLE::D3D11: return 1;
|
||||||
case ANGLE::D3D9: return 2;
|
case ANGLE::D3D9: return 2;
|
||||||
case ANGLE::D3D11on12: return 3;
|
case ANGLE::D3D11on12: return 3;
|
||||||
case ANGLE::OpenGL: return 4;
|
//case ANGLE::OpenGL: return 4;
|
||||||
}
|
}
|
||||||
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
|
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
|
||||||
}();
|
}();
|
||||||
|
@ -764,7 +765,7 @@ void SetupANGLE(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto confirmed = crl::guard(button, [=] {
|
const auto confirmed = crl::guard(button, [=] {
|
||||||
const auto nowDisabled = (index == 5);
|
const auto nowDisabled = (index == disabled);
|
||||||
if (!nowDisabled) {
|
if (!nowDisabled) {
|
||||||
Ui::GL::ChangeANGLE([&] {
|
Ui::GL::ChangeANGLE([&] {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
@ -772,12 +773,12 @@ void SetupANGLE(
|
||||||
case 1: return ANGLE::D3D11;
|
case 1: return ANGLE::D3D11;
|
||||||
case 2: return ANGLE::D3D9;
|
case 2: return ANGLE::D3D9;
|
||||||
case 3: return ANGLE::D3D11on12;
|
case 3: return ANGLE::D3D11on12;
|
||||||
case 4: return ANGLE::OpenGL;
|
//case 4: return ANGLE::OpenGL;
|
||||||
}
|
}
|
||||||
Unexpected("Index in SetupANGLE.");
|
Unexpected("Index in SetupANGLE.");
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
const auto wasDisabled = (backendIndex == 5);
|
const auto wasDisabled = (backendIndex == disabled);
|
||||||
if (nowDisabled != wasDisabled) {
|
if (nowDisabled != wasDisabled) {
|
||||||
Core::App().settings().setDisableOpenGL(nowDisabled);
|
Core::App().settings().setDisableOpenGL(nowDisabled);
|
||||||
Local::writeSettings();
|
Local::writeSettings();
|
||||||
|
|
|
@ -526,7 +526,7 @@ FileLoadTask::FileLoadTask(
|
||||||
FileLoadTask::FileLoadTask(
|
FileLoadTask::FileLoadTask(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QByteArray &voice,
|
const QByteArray &voice,
|
||||||
int32 duration,
|
crl::time duration,
|
||||||
const VoiceWaveform &waveform,
|
const VoiceWaveform &waveform,
|
||||||
const FileLoadTo &to,
|
const FileLoadTo &to,
|
||||||
const TextWithTags &caption)
|
const TextWithTags &caption)
|
||||||
|
@ -852,8 +852,9 @@ void FileLoadTask::process(Args &&args) {
|
||||||
if (auto song = std::get_if<Ui::PreparedFileInformation::Song>(
|
if (auto song = std::get_if<Ui::PreparedFileInformation::Song>(
|
||||||
&_information->media)) {
|
&_information->media)) {
|
||||||
isSong = true;
|
isSong = true;
|
||||||
|
const auto seconds = song->duration / 1000;
|
||||||
auto flags = MTPDdocumentAttributeAudio::Flag::f_title | MTPDdocumentAttributeAudio::Flag::f_performer;
|
auto flags = MTPDdocumentAttributeAudio::Flag::f_title | MTPDdocumentAttributeAudio::Flag::f_performer;
|
||||||
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(song->duration), MTP_string(song->title), MTP_string(song->performer), MTPstring()));
|
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(seconds), MTP_string(song->title), MTP_string(song->performer), MTPstring()));
|
||||||
thumbnail = PrepareFileThumbnail(std::move(song->cover));
|
thumbnail = PrepareFileThumbnail(std::move(song->cover));
|
||||||
} else if (auto video = std::get_if<Ui::PreparedFileInformation::Video>(
|
} else if (auto video = std::get_if<Ui::PreparedFileInformation::Video>(
|
||||||
&_information->media)) {
|
&_information->media)) {
|
||||||
|
@ -867,9 +868,10 @@ void FileLoadTask::process(Args &&args) {
|
||||||
if (video->supportsStreaming) {
|
if (video->supportsStreaming) {
|
||||||
flags |= MTPDdocumentAttributeVideo::Flag::f_supports_streaming;
|
flags |= MTPDdocumentAttributeVideo::Flag::f_supports_streaming;
|
||||||
}
|
}
|
||||||
|
const auto realSeconds = video->duration / 1000.;
|
||||||
attributes.push_back(MTP_documentAttributeVideo(
|
attributes.push_back(MTP_documentAttributeVideo(
|
||||||
MTP_flags(flags),
|
MTP_flags(flags),
|
||||||
MTP_double(video->duration / 1000.),
|
MTP_double(realSeconds),
|
||||||
MTP_int(coverWidth),
|
MTP_int(coverWidth),
|
||||||
MTP_int(coverHeight),
|
MTP_int(coverHeight),
|
||||||
MTPint())); // preload_prefix_size
|
MTPint())); // preload_prefix_size
|
||||||
|
@ -971,8 +973,9 @@ void FileLoadTask::process(Args &&args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVoice) {
|
if (isVoice) {
|
||||||
|
const auto seconds = _duration / 1000;
|
||||||
auto flags = MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform;
|
auto flags = MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform;
|
||||||
attributes[0] = MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
|
attributes[0] = MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(seconds), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
|
||||||
attributes.resize(1);
|
attributes.resize(1);
|
||||||
document = MTP_document(
|
document = MTP_document(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
|
|
|
@ -256,7 +256,7 @@ public:
|
||||||
FileLoadTask(
|
FileLoadTask(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QByteArray &voice,
|
const QByteArray &voice,
|
||||||
int32 duration,
|
crl::time duration,
|
||||||
const VoiceWaveform &waveform,
|
const VoiceWaveform &waveform,
|
||||||
const FileLoadTo &to,
|
const FileLoadTo &to,
|
||||||
const TextWithTags &caption);
|
const TextWithTags &caption);
|
||||||
|
@ -306,7 +306,7 @@ private:
|
||||||
QString _filepath;
|
QString _filepath;
|
||||||
QByteArray _content;
|
QByteArray _content;
|
||||||
std::unique_ptr<Ui::PreparedFileInformation> _information;
|
std::unique_ptr<Ui::PreparedFileInformation> _information;
|
||||||
int32 _duration = 0;
|
crl::time _duration = 0;
|
||||||
VoiceWaveform _waveform;
|
VoiceWaveform _waveform;
|
||||||
SendMediaType _type;
|
SendMediaType _type;
|
||||||
TextWithTags _caption;
|
TextWithTags _caption;
|
||||||
|
|
|
@ -259,8 +259,7 @@ void AlbumThumbnail::paintInAlbum(
|
||||||
|
|
||||||
_lastRectOfButtons = paintButtons(
|
_lastRectOfButtons = paintButtons(
|
||||||
p,
|
p,
|
||||||
geometry.topLeft(),
|
geometry,
|
||||||
geometry.width(),
|
|
||||||
shrinkProgress);
|
shrinkProgress);
|
||||||
_lastRectOfModify = geometry;
|
_lastRectOfModify = geometry;
|
||||||
}
|
}
|
||||||
|
@ -460,8 +459,7 @@ void AlbumThumbnail::paintPhoto(Painter &p, int left, int top, int outerWidth) {
|
||||||
|
|
||||||
_lastRectOfButtons = paintButtons(
|
_lastRectOfButtons = paintButtons(
|
||||||
p,
|
p,
|
||||||
topLeft,
|
QRect(left, top, st::sendMediaPreviewSize, size.height()),
|
||||||
st::sendMediaPreviewSize,
|
|
||||||
0);
|
0);
|
||||||
|
|
||||||
_lastRectOfModify = QRect(topLeft, size);
|
_lastRectOfModify = QRect(topLeft, size);
|
||||||
|
@ -521,7 +519,9 @@ AttachButtonType AlbumThumbnail::buttonTypeFromPoint(QPoint position) const {
|
||||||
}
|
}
|
||||||
return (!_lastRectOfButtons.contains(position) && !_isCompressedSticker)
|
return (!_lastRectOfButtons.contains(position) && !_isCompressedSticker)
|
||||||
? AttachButtonType::Modify
|
? AttachButtonType::Modify
|
||||||
: (position.x() < _lastRectOfButtons.center().x())
|
: (_buttons.vertical()
|
||||||
|
? (position.y() < _lastRectOfButtons.center().y())
|
||||||
|
: (position.x() < _lastRectOfButtons.center().x()))
|
||||||
? AttachButtonType::Edit
|
? AttachButtonType::Edit
|
||||||
: AttachButtonType::Delete;
|
: AttachButtonType::Delete;
|
||||||
}
|
}
|
||||||
|
@ -585,24 +585,31 @@ void AlbumThumbnail::finishAnimations() {
|
||||||
|
|
||||||
QRect AlbumThumbnail::paintButtons(
|
QRect AlbumThumbnail::paintButtons(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
QPoint point,
|
QRect geometry,
|
||||||
int outerWidth,
|
|
||||||
float64 shrinkProgress) {
|
float64 shrinkProgress) {
|
||||||
const auto &skipRight = st::sendBoxAlbumGroupSkipRight;
|
const auto &skipRight = st::sendBoxAlbumGroupSkipRight;
|
||||||
const auto &skipTop = st::sendBoxAlbumGroupSkipTop;
|
const auto &skipTop = st::sendBoxAlbumGroupSkipTop;
|
||||||
const auto groupWidth = _buttons.width();
|
const auto outerWidth = geometry.width();
|
||||||
|
const auto outerHeight = geometry.height();
|
||||||
// If the width is tiny, it would be better to not display the buttons.
|
if (st::sendBoxAlbumGroupSize.width() <= outerWidth) {
|
||||||
if (groupWidth > outerWidth) {
|
_buttons.setVertical(false);
|
||||||
|
} else if (st::sendBoxAlbumGroupSize.height() <= outerHeight) {
|
||||||
|
_buttons.setVertical(true);
|
||||||
|
} else {
|
||||||
|
// If the size is tiny, skip the buttons.
|
||||||
return QRect();
|
return QRect();
|
||||||
}
|
}
|
||||||
|
const auto groupWidth = _buttons.width();
|
||||||
|
const auto groupHeight = _buttons.height();
|
||||||
|
|
||||||
// If the width is too small,
|
// If the width is too small,
|
||||||
// it would be better to display the buttons in the center.
|
// it would be better to display the buttons in the center.
|
||||||
const auto groupX = point.x() + ((groupWidth + skipRight * 2 > outerWidth)
|
const auto groupX = geometry.x() + ((groupWidth + skipRight * 2 > outerWidth)
|
||||||
? (outerWidth - groupWidth) / 2
|
? (outerWidth - groupWidth) / 2
|
||||||
: outerWidth - skipRight - groupWidth);
|
: outerWidth - skipRight - groupWidth);
|
||||||
const auto groupY = point.y() + skipTop;
|
const auto groupY = geometry.y() + ((groupHeight + skipTop * 2 > outerHeight)
|
||||||
|
? (outerHeight - groupHeight) / 2
|
||||||
|
: skipTop);
|
||||||
|
|
||||||
const auto opacity = p.opacity();
|
const auto opacity = p.opacity();
|
||||||
p.setOpacity(1.0 - shrinkProgress);
|
p.setOpacity(1.0 - shrinkProgress);
|
||||||
|
|
|
@ -78,8 +78,7 @@ private:
|
||||||
void drawSimpleFrame(QPainter &p, QRect to, QSize size) const;
|
void drawSimpleFrame(QPainter &p, QRect to, QSize size) const;
|
||||||
QRect paintButtons(
|
QRect paintButtons(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
QPoint point,
|
QRect geometry,
|
||||||
int outerWidth,
|
|
||||||
float64 shrinkProgress);
|
float64 shrinkProgress);
|
||||||
void paintPlayVideo(QPainter &p, QRect geometry);
|
void paintPlayVideo(QPainter &p, QRect geometry);
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,15 @@ void AttachControls::paint(QPainter &p, int x, int y) {
|
||||||
|
|
||||||
if (full) {
|
if (full) {
|
||||||
const auto groupHalfWidth = groupWidth / 2;
|
const auto groupHalfWidth = groupWidth / 2;
|
||||||
QRect leftRect(x, y, groupHalfWidth, groupHeight);
|
const auto groupHalfHeight = groupHeight / 2;
|
||||||
st::sendBoxAlbumGroupButtonMediaEdit.paintInCenter(p, leftRect);
|
const auto editRect = _vertical
|
||||||
QRect rightRect(x + groupHalfWidth, y, groupHalfWidth, groupHeight);
|
? QRect(x, y, groupWidth, groupHalfHeight)
|
||||||
st::sendBoxAlbumGroupButtonMediaDelete.paintInCenter(p, rightRect);
|
: QRect(x, y, groupHalfWidth, groupHeight);
|
||||||
|
st::sendBoxAlbumGroupButtonMediaEdit.paintInCenter(p, editRect);
|
||||||
|
const auto deleteRect = _vertical
|
||||||
|
? QRect(x, y + groupHalfHeight, groupWidth, groupHalfHeight)
|
||||||
|
: QRect(x + groupHalfWidth, y, groupHalfWidth, groupHeight);
|
||||||
|
st::sendBoxAlbumGroupButtonMediaDelete.paintInCenter(p, deleteRect);
|
||||||
} else if (_type == Type::EditOnly) {
|
} else if (_type == Type::EditOnly) {
|
||||||
st::sendBoxAlbumButtonMediaEdit.paintInCenter(p, groupRect);
|
st::sendBoxAlbumButtonMediaEdit.paintInCenter(p, groupRect);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +41,9 @@ void AttachControls::paint(QPainter &p, int x, int y) {
|
||||||
|
|
||||||
int AttachControls::width() const {
|
int AttachControls::width() const {
|
||||||
return (_type == Type::Full)
|
return (_type == Type::Full)
|
||||||
? st::sendBoxAlbumGroupSize.width()
|
? (_vertical
|
||||||
|
? st::sendBoxAlbumGroupSizeVertical.width()
|
||||||
|
: st::sendBoxAlbumGroupSize.width())
|
||||||
: (_type == Type::EditOnly)
|
: (_type == Type::EditOnly)
|
||||||
? st::sendBoxAlbumSmallGroupSize.width()
|
? st::sendBoxAlbumSmallGroupSize.width()
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -44,7 +51,9 @@ int AttachControls::width() const {
|
||||||
|
|
||||||
int AttachControls::height() const {
|
int AttachControls::height() const {
|
||||||
return (_type == Type::Full)
|
return (_type == Type::Full)
|
||||||
? st::sendBoxAlbumGroupSize.height()
|
? (_vertical
|
||||||
|
? st::sendBoxAlbumGroupSizeVertical.height()
|
||||||
|
: st::sendBoxAlbumGroupSize.height())
|
||||||
: (_type == Type::EditOnly)
|
: (_type == Type::EditOnly)
|
||||||
? st::sendBoxAlbumSmallGroupSize.height()
|
? st::sendBoxAlbumSmallGroupSize.height()
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -54,12 +63,20 @@ AttachControls::Type AttachControls::type() const {
|
||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AttachControls::vertical() const {
|
||||||
|
return _vertical;
|
||||||
|
}
|
||||||
|
|
||||||
void AttachControls::setType(Type type) {
|
void AttachControls::setType(Type type) {
|
||||||
if (_type != type) {
|
if (_type != type) {
|
||||||
_type = type;
|
_type = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AttachControls::setVertical(bool vertical) {
|
||||||
|
_vertical = vertical;
|
||||||
|
}
|
||||||
|
|
||||||
AttachControlsWidget::AttachControlsWidget(
|
AttachControlsWidget::AttachControlsWidget(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
AttachControls::Type type)
|
AttachControls::Type type)
|
||||||
|
|
|
@ -25,14 +25,17 @@ public:
|
||||||
|
|
||||||
void paint(QPainter &p, int x, int y);
|
void paint(QPainter &p, int x, int y);
|
||||||
void setType(Type type);
|
void setType(Type type);
|
||||||
|
void setVertical(bool vertical);
|
||||||
|
|
||||||
[[nodiscard]] int width() const;
|
[[nodiscard]] int width() const;
|
||||||
[[nodiscard]] int height() const;
|
[[nodiscard]] int height() const;
|
||||||
[[nodiscard]] Type type() const;
|
[[nodiscard]] Type type() const;
|
||||||
|
[[nodiscard]] bool vertical() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RoundRect _rect;
|
RoundRect _rect;
|
||||||
Type _type = Type::Full;
|
Type _type = Type::Full;
|
||||||
|
bool _vertical = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct PreparedFileInformation {
|
||||||
Editor::PhotoModifications modifications;
|
Editor::PhotoModifications modifications;
|
||||||
};
|
};
|
||||||
struct Song {
|
struct Song {
|
||||||
int duration = -1;
|
crl::time duration = -1;
|
||||||
QString title;
|
QString title;
|
||||||
QString performer;
|
QString performer;
|
||||||
QImage cover;
|
QImage cover;
|
||||||
|
|
|
@ -523,7 +523,7 @@ historyFastShareSize: 31px;
|
||||||
historyFastShareLeft: 13px;
|
historyFastShareLeft: 13px;
|
||||||
historyFastShareBottom: 5px;
|
historyFastShareBottom: 5px;
|
||||||
historyFastShareIcon: icon {{ "fast_share", msgServiceFg }};
|
historyFastShareIcon: icon {{ "fast_share", msgServiceFg }};
|
||||||
historyGoToOriginalIcon: icon {{ "fast_to_original", msgServiceFg }};
|
historyGoToOriginalIcon: icon {{ "fast_to_original", msgServiceFg, point(1px, 0px) }};
|
||||||
historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }};
|
historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }};
|
||||||
historyFastTranscribeIcon: icon {{ "chat/voice_to_text", msgServiceFg }};
|
historyFastTranscribeIcon: icon {{ "chat/voice_to_text", msgServiceFg }};
|
||||||
|
|
||||||
|
|
|
@ -31,23 +31,29 @@ SilentToggle::SilentToggle(QWidget *parent, not_null<ChannelData*> channel)
|
||||||
|
|
||||||
resize(_st.width, _st.height);
|
resize(_st.width, _st.height);
|
||||||
|
|
||||||
paintRequest(
|
|
||||||
) | rpl::start_with_next([=](const QRect &clip) {
|
|
||||||
auto p = QPainter(this);
|
|
||||||
paintRipple(p, _st.rippleAreaPosition, nullptr);
|
|
||||||
|
|
||||||
//const auto checked = _crossLineAnimation.value(_checked ? 1. : 0.);
|
|
||||||
const auto over = isOver();
|
|
||||||
(_checked
|
|
||||||
? (over
|
|
||||||
? st::historySilentToggleOnOver
|
|
||||||
: st::historySilentToggleOn)
|
|
||||||
: (over
|
|
||||||
? st::historySilentToggle.iconOver
|
|
||||||
: st::historySilentToggle.icon)).paintInCenter(p, rect());
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
|
clicks(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
setChecked(!_checked);
|
||||||
|
Ui::Tooltip::Show(0, this);
|
||||||
|
_channel->owner().notifySettings().update(_channel, {}, _checked);
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SilentToggle::paintEvent(QPaintEvent *e) {
|
||||||
|
auto p = QPainter(this);
|
||||||
|
paintRipple(p, _st.rippleAreaPosition, nullptr);
|
||||||
|
|
||||||
|
//const auto checked = _crossLineAnimation.value(_checked ? 1. : 0.);
|
||||||
|
const auto over = isOver();
|
||||||
|
(_checked
|
||||||
|
? (over
|
||||||
|
? st::historySilentToggleOnOver
|
||||||
|
: st::historySilentToggleOn)
|
||||||
|
: (over
|
||||||
|
? st::historySilentToggle.iconOver
|
||||||
|
: st::historySilentToggle.icon)).paintInCenter(p, rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SilentToggle::mouseMoveEvent(QMouseEvent *e) {
|
void SilentToggle::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
@ -62,11 +68,12 @@ void SilentToggle::mouseMoveEvent(QMouseEvent *e) {
|
||||||
void SilentToggle::setChecked(bool checked) {
|
void SilentToggle::setChecked(bool checked) {
|
||||||
if (_checked != checked) {
|
if (_checked != checked) {
|
||||||
_checked = checked;
|
_checked = checked;
|
||||||
_crossLineAnimation.start(
|
update();
|
||||||
[=] { update(); },
|
// _crossLineAnimation.start(
|
||||||
_checked ? 0. : 1.,
|
// [=] { update(); },
|
||||||
_checked ? 1. : 0.,
|
// _checked ? 0. : 1.,
|
||||||
kAnimationDuration);
|
// _checked ? 1. : 0.,
|
||||||
|
// kAnimationDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +82,6 @@ void SilentToggle::leaveEventHook(QEvent *e) {
|
||||||
Ui::Tooltip::Hide();
|
Ui::Tooltip::Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SilentToggle::mouseReleaseEvent(QMouseEvent *e) {
|
|
||||||
setChecked(!_checked);
|
|
||||||
RippleButton::mouseReleaseEvent(e);
|
|
||||||
Ui::Tooltip::Show(0, this);
|
|
||||||
_channel->owner().notifySettings().update(_channel, {}, _checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SilentToggle::tooltipText() const {
|
QString SilentToggle::tooltipText() const {
|
||||||
return _checked
|
return _checked
|
||||||
? tr::lng_wont_be_notified(tr::now)
|
? tr::lng_wont_be_notified(tr::now)
|
||||||
|
|
|
@ -29,8 +29,8 @@ public:
|
||||||
bool tooltipWindowActive() const override;
|
bool tooltipWindowActive() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
|
||||||
QImage prepareRippleMask() const override;
|
QImage prepareRippleMask() const override;
|
||||||
|
@ -42,7 +42,7 @@ private:
|
||||||
not_null<ChannelData*> _channel;
|
not_null<ChannelData*> _channel;
|
||||||
bool _checked = false;
|
bool _checked = false;
|
||||||
|
|
||||||
Animations::Simple _crossLineAnimation;
|
// Animations::Simple _crossLineAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
DiscreteSlider::DiscreteSlider(QWidget *parent) : RpWidget(parent) {
|
DiscreteSlider::DiscreteSlider(QWidget *parent, bool snapToLabel)
|
||||||
|
: RpWidget(parent)
|
||||||
|
, _snapToLabel(snapToLabel) {
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +82,23 @@ void DiscreteSlider::setSections(const std::vector<QString> &labels) {
|
||||||
resizeToWidth(width());
|
resizeToWidth(width());
|
||||||
}
|
}
|
||||||
|
|
||||||
int DiscreteSlider::getCurrentActiveLeft() {
|
DiscreteSlider::Range DiscreteSlider::getFinalActiveRange() const {
|
||||||
const auto left = _sections.empty() ? 0 : _sections[_selected].left;
|
const auto raw = _sections.empty() ? nullptr : &_sections[_selected];
|
||||||
return _a_left.value(left);
|
if (!raw) {
|
||||||
|
return { 0, 0 };
|
||||||
|
}
|
||||||
|
const auto width = _snapToLabel
|
||||||
|
? std::min(raw->width, raw->label.maxWidth())
|
||||||
|
: raw->width;
|
||||||
|
return { raw->left + ((raw->width - width) / 2), width };
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscreteSlider::Range DiscreteSlider::getCurrentActiveRange() const {
|
||||||
|
const auto to = getFinalActiveRange();
|
||||||
|
return {
|
||||||
|
int(base::SafeRound(_a_left.value(to.left))),
|
||||||
|
int(base::SafeRound(_a_width.value(to.width))),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Lambda>
|
template <typename Lambda>
|
||||||
|
@ -138,11 +154,13 @@ void DiscreteSlider::setSelectedSection(int index) {
|
||||||
if (index < 0 || index >= _sections.size()) return;
|
if (index < 0 || index >= _sections.size()) return;
|
||||||
|
|
||||||
if (_selected != index) {
|
if (_selected != index) {
|
||||||
auto from = _sections[_selected].left;
|
const auto from = getFinalActiveRange();
|
||||||
_selected = index;
|
_selected = index;
|
||||||
auto to = _sections[_selected].left;
|
const auto to = getFinalActiveRange();
|
||||||
auto duration = getAnimationDuration();
|
const auto duration = getAnimationDuration();
|
||||||
_a_left.start([this] { update(); }, from, to, duration);
|
const auto updater = [=] { update(); };
|
||||||
|
_a_left.start(updater, from.left, to.left, duration);
|
||||||
|
_a_width.start(updater, from.width, to.width, duration);
|
||||||
_callbackAfterMs = crl::now() + duration;
|
_callbackAfterMs = crl::now() + duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +184,7 @@ DiscreteSlider::Section::Section(
|
||||||
SettingsSlider::SettingsSlider(
|
SettingsSlider::SettingsSlider(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
const style::SettingsSlider &st)
|
const style::SettingsSlider &st)
|
||||||
: DiscreteSlider(parent)
|
: DiscreteSlider(parent, st.barSnapToLabel)
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
if (_st.barRadius > 0) {
|
if (_st.barRadius > 0) {
|
||||||
_bar.emplace(_st.barRadius, _st.barFg);
|
_bar.emplace(_st.barRadius, _st.barFg);
|
||||||
|
@ -299,7 +317,7 @@ void SettingsSlider::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
auto clip = e->rect();
|
auto clip = e->rect();
|
||||||
auto activeLeft = getCurrentActiveLeft();
|
auto range = getCurrentActiveRange();
|
||||||
|
|
||||||
const auto drawRect = [&](QRect rect, bool active = false) {
|
const auto drawRect = [&](QRect rect, bool active = false) {
|
||||||
const auto &bar = active ? _barActive : _bar;
|
const auto &bar = active ? _barActive : _bar;
|
||||||
|
@ -310,9 +328,14 @@ void SettingsSlider::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
enumerateSections([&](Section §ion) {
|
enumerateSections([&](Section §ion) {
|
||||||
|
const auto activeWidth = _st.barSnapToLabel
|
||||||
|
? section.label.maxWidth()
|
||||||
|
: section.width;
|
||||||
|
const auto activeLeft = section.left
|
||||||
|
+ (section.width - activeWidth) / 2;
|
||||||
auto active = 1.
|
auto active = 1.
|
||||||
- std::clamp(
|
- std::clamp(
|
||||||
qAbs(activeLeft - section.left) / float64(section.width),
|
qAbs(range.left - activeLeft) / float64(section.width),
|
||||||
0.,
|
0.,
|
||||||
1.);
|
1.);
|
||||||
if (section.ripple) {
|
if (section.ripple) {
|
||||||
|
@ -322,36 +345,47 @@ void SettingsSlider::paintEvent(QPaintEvent *e) {
|
||||||
section.ripple.reset();
|
section.ripple.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto from = section.left, tofill = section.width;
|
if (!_st.barSnapToLabel) {
|
||||||
if (activeLeft > from) {
|
auto from = activeLeft, tofill = activeWidth;
|
||||||
auto fill = qMin(tofill, activeLeft - from);
|
if (range.left > from) {
|
||||||
drawRect(myrtlrect(from, _st.barTop, fill, _st.barStroke));
|
auto fill = qMin(tofill, range.left - from);
|
||||||
from += fill;
|
drawRect(myrtlrect(from, _st.barTop, fill, _st.barStroke));
|
||||||
tofill -= fill;
|
|
||||||
}
|
|
||||||
if (activeLeft + section.width > from) {
|
|
||||||
if (auto fill = qMin(tofill, activeLeft + section.width - from)) {
|
|
||||||
drawRect(
|
|
||||||
myrtlrect(from, _st.barTop, fill, _st.barStroke),
|
|
||||||
true);
|
|
||||||
from += fill;
|
from += fill;
|
||||||
tofill -= fill;
|
tofill -= fill;
|
||||||
}
|
}
|
||||||
|
if (range.left + activeWidth > from) {
|
||||||
|
if (auto fill = qMin(tofill, range.left + activeWidth - from)) {
|
||||||
|
drawRect(
|
||||||
|
myrtlrect(from, _st.barTop, fill, _st.barStroke),
|
||||||
|
true);
|
||||||
|
from += fill;
|
||||||
|
tofill -= fill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tofill) {
|
||||||
|
drawRect(myrtlrect(from, _st.barTop, tofill, _st.barStroke));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tofill) {
|
const auto labelLeft = section.left + (section.width - section.label.maxWidth()) / 2;
|
||||||
drawRect(myrtlrect(from, _st.barTop, tofill, _st.barStroke));
|
if (myrtlrect(labelLeft, _st.labelTop, section.label.maxWidth(), _st.labelStyle.font->height).intersects(clip)) {
|
||||||
}
|
|
||||||
if (myrtlrect(section.left, _st.labelTop, section.width, _st.labelStyle.font->height).intersects(clip)) {
|
|
||||||
p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
|
p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
|
||||||
section.label.drawLeft(
|
section.label.drawLeft(
|
||||||
p,
|
p,
|
||||||
section.left + (section.width - section.label.maxWidth()) / 2,
|
labelLeft,
|
||||||
_st.labelTop,
|
_st.labelTop,
|
||||||
section.label.maxWidth(),
|
section.label.maxWidth(),
|
||||||
width());
|
width());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
if (_st.barSnapToLabel) {
|
||||||
|
const auto add = _st.barStroke / 2;
|
||||||
|
const auto from = std::max(range.left - add, 0);
|
||||||
|
const auto till = std::min(range.left + range.width + add, width());
|
||||||
|
if (from < till) {
|
||||||
|
drawRect(myrtlrect(from, _st.barTop, till - from, _st.barStroke), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -18,7 +18,7 @@ class RippleAnimation;
|
||||||
|
|
||||||
class DiscreteSlider : public RpWidget {
|
class DiscreteSlider : public RpWidget {
|
||||||
public:
|
public:
|
||||||
DiscreteSlider(QWidget *parent);
|
DiscreteSlider(QWidget *parent, bool snapToLabel);
|
||||||
|
|
||||||
void addSection(const QString &label);
|
void addSection(const QString &label);
|
||||||
void setSections(const std::vector<QString> &labels);
|
void setSections(const std::vector<QString> &labels);
|
||||||
|
@ -49,10 +49,15 @@ protected:
|
||||||
Ui::Text::String label;
|
Ui::Text::String label;
|
||||||
std::unique_ptr<RippleAnimation> ripple;
|
std::unique_ptr<RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
|
struct Range {
|
||||||
|
int left = 0;
|
||||||
|
int width = 0;
|
||||||
|
};
|
||||||
|
|
||||||
int getCurrentActiveLeft();
|
[[nodiscard]] Range getFinalActiveRange() const;
|
||||||
|
[[nodiscard]] Range getCurrentActiveRange() const;
|
||||||
|
|
||||||
int getSectionsCount() const {
|
[[nodiscard]] int getSectionsCount() const {
|
||||||
return _sections.size();
|
return _sections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +72,7 @@ protected:
|
||||||
|
|
||||||
void stopAnimation() {
|
void stopAnimation() {
|
||||||
_a_left.stop();
|
_a_left.stop();
|
||||||
|
_a_width.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSelectOnPress(bool selectOnPress);
|
void setSelectOnPress(bool selectOnPress);
|
||||||
|
@ -82,12 +88,14 @@ private:
|
||||||
std::vector<Section> _sections;
|
std::vector<Section> _sections;
|
||||||
int _activeIndex = 0;
|
int _activeIndex = 0;
|
||||||
bool _selectOnPress = true;
|
bool _selectOnPress = true;
|
||||||
|
bool _snapToLabel = false;
|
||||||
|
|
||||||
rpl::event_stream<int> _sectionActivated;
|
rpl::event_stream<int> _sectionActivated;
|
||||||
|
|
||||||
int _pressed = -1;
|
int _pressed = -1;
|
||||||
int _selected = 0;
|
int _selected = 0;
|
||||||
Ui::Animations::Simple _a_left;
|
Ui::Animations::Simple _a_left;
|
||||||
|
Ui::Animations::Simple _a_width;
|
||||||
|
|
||||||
int _timerId = -1;
|
int _timerId = -1;
|
||||||
crl::time _callbackAfterMs = 0;
|
crl::time _callbackAfterMs = 0;
|
||||||
|
|
|
@ -40,9 +40,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
#if __has_include(<giomm.h>)
|
#if __has_include(<gio/gio.hpp>)
|
||||||
#include <giomm.h>
|
#include <gio/gio.hpp>
|
||||||
#endif // __has_include(<giomm.h>)
|
#endif // __has_include(<gio/gio.hpp>)
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
@ -90,11 +90,12 @@ base::options::toggle OptionGNotification({
|
||||||
.description = "Force enable GLib's GNotification."
|
.description = "Force enable GLib's GNotification."
|
||||||
" When disabled, autodetect is used.",
|
" When disabled, autodetect is used.",
|
||||||
.scope = [] {
|
.scope = [] {
|
||||||
#if __has_include(<giomm.h>)
|
#if __has_include(<gio/gio.hpp>)
|
||||||
|
using namespace gi::repository;
|
||||||
return bool(Gio::Application::get_default());
|
return bool(Gio::Application::get_default());
|
||||||
#else // __has_include(<giomm.h>)
|
#else // __has_include(<gio/gio.hpp>)
|
||||||
return false;
|
return false;
|
||||||
#endif // __has_include(<giomm.h>)
|
#endif // __has_include(<gio/gio.hpp>)
|
||||||
},
|
},
|
||||||
.restartRequired = true,
|
.restartRequired = true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,7 @@ RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.n
|
||||||
autoconf automake libtool patch gperf flex \
|
autoconf automake libtool patch gperf flex \
|
||||||
fontconfig-devel freetype-devel libX11-devel at-spi2-core-devel alsa-lib-devel \
|
fontconfig-devel freetype-devel libX11-devel at-spi2-core-devel alsa-lib-devel \
|
||||||
pulseaudio-libs-devel mesa-libGL-devel mesa-libEGL-devel mesa-libgbm-devel \
|
pulseaudio-libs-devel mesa-libGL-devel mesa-libEGL-devel mesa-libgbm-devel \
|
||||||
libdrm-devel vulkan-devel boost169-devel fmt-devel \
|
libdrm-devel vulkan-devel libva-devel libvdpau-devel boost169-devel fmt-devel \
|
||||||
gtk3-devel perl-XML-Parser pkgconfig bison yasm file which xorg-x11-util-macros \
|
gtk3-devel perl-XML-Parser pkgconfig bison yasm file which xorg-x11-util-macros \
|
||||||
devtoolset-10-make devtoolset-10-gcc devtoolset-10-gcc-c++ \
|
devtoolset-10-make devtoolset-10-gcc devtoolset-10-gcc-c++ \
|
||||||
devtoolset-10-binutils llvm-toolset-7.0 llvm-toolset-7.0-clang-devel \
|
devtoolset-10-binutils llvm-toolset-7.0 llvm-toolset-7.0-clang-devel \
|
||||||
|
@ -420,6 +420,17 @@ RUN git clone -b libXfixes-5.0.3 --depth=1 {{ GIT_FREEDESKTOP }}/libxfixes.git \
|
||||||
&& cd .. \
|
&& cd .. \
|
||||||
&& rm -rf libxfixes
|
&& rm -rf libxfixes
|
||||||
|
|
||||||
|
FROM builder AS libXv
|
||||||
|
COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
|
||||||
|
|
||||||
|
RUN git clone -b libXv-1.0.12 --depth=1 {{ GIT_FREEDESKTOP }}/libxv.git \
|
||||||
|
&& cd libxv \
|
||||||
|
&& ./autogen.sh --enable-static \
|
||||||
|
&& make -j$(nproc) \
|
||||||
|
&& make DESTDIR="{{ LibrariesPath }}/libXv-cache" install \
|
||||||
|
&& cd .. \
|
||||||
|
&& rm -rf libxv
|
||||||
|
|
||||||
FROM builder AS libXrandr
|
FROM builder AS libXrandr
|
||||||
RUN git clone -b libXrandr-1.5.2 --depth=1 {{ GIT_FREEDESKTOP }}/libxrandr.git \
|
RUN git clone -b libXrandr-1.5.2 --depth=1 {{ GIT_FREEDESKTOP }}/libxrandr.git \
|
||||||
&& cd libxrandr \
|
&& cd libxrandr \
|
||||||
|
@ -482,6 +493,8 @@ FROM builder AS ffmpeg
|
||||||
COPY --link --from=opus {{ LibrariesPath }}/opus-cache /
|
COPY --link --from=opus {{ LibrariesPath }}/opus-cache /
|
||||||
COPY --link --from=dav1d {{ LibrariesPath }}/dav1d-cache /
|
COPY --link --from=dav1d {{ LibrariesPath }}/dav1d-cache /
|
||||||
COPY --link --from=libvpx {{ LibrariesPath }}/libvpx-cache /
|
COPY --link --from=libvpx {{ LibrariesPath }}/libvpx-cache /
|
||||||
|
COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
|
||||||
|
COPY --link --from=libXv {{ LibrariesPath }}/libXv-cache /
|
||||||
COPY --link --from=nv-codec-headers {{ LibrariesPath }}/nv-codec-headers-cache /
|
COPY --link --from=nv-codec-headers {{ LibrariesPath }}/nv-codec-headers-cache /
|
||||||
|
|
||||||
RUN git init ffmpeg \
|
RUN git init ffmpeg \
|
||||||
|
@ -503,15 +516,29 @@ RUN git init ffmpeg \
|
||||||
--enable-libdav1d \
|
--enable-libdav1d \
|
||||||
--enable-libopus \
|
--enable-libopus \
|
||||||
--enable-libvpx \
|
--enable-libvpx \
|
||||||
|
--enable-vaapi \
|
||||||
|
--enable-vdpau \
|
||||||
|
--enable-xlib \
|
||||||
|
--enable-libdrm \
|
||||||
--enable-ffnvcodec \
|
--enable-ffnvcodec \
|
||||||
--enable-nvdec \
|
--enable-nvdec \
|
||||||
--enable-cuvid \
|
--enable-cuvid \
|
||||||
--enable-protocol=file \
|
--enable-protocol=file \
|
||||||
|
--enable-hwaccel=av1_vaapi \
|
||||||
--enable-hwaccel=av1_nvdec \
|
--enable-hwaccel=av1_nvdec \
|
||||||
|
--enable-hwaccel=h264_vaapi \
|
||||||
|
--enable-hwaccel=h264_vdpau \
|
||||||
--enable-hwaccel=h264_nvdec \
|
--enable-hwaccel=h264_nvdec \
|
||||||
|
--enable-hwaccel=hevc_vaapi \
|
||||||
|
--enable-hwaccel=hevc_vdpau \
|
||||||
--enable-hwaccel=hevc_nvdec \
|
--enable-hwaccel=hevc_nvdec \
|
||||||
|
--enable-hwaccel=mpeg2_vaapi \
|
||||||
|
--enable-hwaccel=mpeg2_vdpau \
|
||||||
--enable-hwaccel=mpeg2_nvdec \
|
--enable-hwaccel=mpeg2_nvdec \
|
||||||
|
--enable-hwaccel=mpeg4_vaapi \
|
||||||
|
--enable-hwaccel=mpeg4_vdpau \
|
||||||
--enable-hwaccel=mpeg4_nvdec \
|
--enable-hwaccel=mpeg4_nvdec \
|
||||||
|
--enable-hwaccel=vp8_vaapi \
|
||||||
--enable-hwaccel=vp8_nvdec \
|
--enable-hwaccel=vp8_nvdec \
|
||||||
--enable-decoder=aac \
|
--enable-decoder=aac \
|
||||||
--enable-decoder=aac_fixed \
|
--enable-decoder=aac_fixed \
|
||||||
|
@ -839,6 +866,7 @@ COPY --link --from=xcb-render-util {{ LibrariesPath }}/xcb-render-util-cache /
|
||||||
COPY --link --from=xcb-cursor {{ LibrariesPath }}/xcb-cursor-cache /
|
COPY --link --from=xcb-cursor {{ LibrariesPath }}/xcb-cursor-cache /
|
||||||
COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
|
COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
|
||||||
COPY --link --from=libXfixes {{ LibrariesPath }}/libXfixes-cache /
|
COPY --link --from=libXfixes {{ LibrariesPath }}/libXfixes-cache /
|
||||||
|
COPY --link --from=libXv {{ LibrariesPath }}/libXv-cache /
|
||||||
COPY --link --from=libXtst {{ LibrariesPath }}/libXtst-cache /
|
COPY --link --from=libXtst {{ LibrariesPath }}/libXtst-cache /
|
||||||
COPY --link --from=libXrandr {{ LibrariesPath }}/libXrandr-cache /
|
COPY --link --from=libXrandr {{ LibrariesPath }}/libXrandr-cache /
|
||||||
COPY --link --from=libXrender {{ LibrariesPath }}/libXrender-cache /
|
COPY --link --from=libXrender {{ LibrariesPath }}/libXrender-cache /
|
||||||
|
|
|
@ -6,5 +6,6 @@ popd > /dev/null
|
||||||
|
|
||||||
|
|
||||||
cd $FullScriptPath/../docker/centos_env
|
cd $FullScriptPath/../docker/centos_env
|
||||||
|
poetry install
|
||||||
poetry run gen_dockerfile | DOCKER_BUILDKIT=1 docker build -t tdesktop:centos_env -
|
poetry run gen_dockerfile | DOCKER_BUILDKIT=1 docker build -t tdesktop:centos_env -
|
||||||
cd $FullExecPath
|
cd $FullExecPath
|
||||||
|
|
|
@ -1210,7 +1210,7 @@ stage('tg_angle', """
|
||||||
win:
|
win:
|
||||||
git clone https://github.com/desktop-app/tg_angle.git
|
git clone https://github.com/desktop-app/tg_angle.git
|
||||||
cd tg_angle
|
cd tg_angle
|
||||||
git checkout 0bb011f9e4
|
git checkout e3f59e8d0c
|
||||||
mkdir out
|
mkdir out
|
||||||
cd out
|
cd out
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
AppVersion 4008010
|
AppVersion 4008011
|
||||||
AppVersionStrMajor 4.8
|
AppVersionStrMajor 4.8
|
||||||
AppVersionStrSmall 4.8.10
|
AppVersionStrSmall 4.8.11
|
||||||
AppVersionStr 4.8.10
|
AppVersionStr 4.8.11
|
||||||
BetaChannel 0
|
BetaChannel 1
|
||||||
AlphaVersion 0
|
AlphaVersion 0
|
||||||
AppVersionOriginal 4.8.10
|
AppVersionOriginal 4.8.11.beta
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5a11029c461416407a423ac9921356fba0088ab6
|
Subproject commit 2d03abc7de8558ae8862688a226b3d5a817dc466
|
|
@ -1 +1 @@
|
||||||
Subproject commit efd052594db9f3d85a2fbcba76db6fdecf226597
|
Subproject commit e497dc134de3f8e2933ee0acdbba8bd702ce2130
|
|
@ -1 +1 @@
|
||||||
Subproject commit ebb8b8b91fe357b2c397a3eb98655c585b8c856e
|
Subproject commit 5850566934f2f6cae56646c36cb95f85c8a9c752
|
|
@ -1,3 +1,9 @@
|
||||||
|
4.8.11 beta (10.08.23)
|
||||||
|
|
||||||
|
- Fix initial video playback speed.
|
||||||
|
- Use native window resize on Windows 11.
|
||||||
|
- Fix memory leak in Direct3D 11 media viewer on Windows.
|
||||||
|
|
||||||
4.8.10 (28.07.23)
|
4.8.10 (28.07.23)
|
||||||
|
|
||||||
- Send story sharing comments as separate messages.
|
- Send story sharing comments as separate messages.
|
||||||
|
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 0620bb7b87a0ec9195151fd5eb0cf38656c1280b
|
Subproject commit ae0986c9efd28c61783cfe106f8bd1b0ba3b3920
|
|
@ -1,23 +1,23 @@
|
||||||
## Build instructions for Linux using Docker
|
## Build instructions for Linux using Docker
|
||||||
|
|
||||||
|
### Prepare folder
|
||||||
|
|
||||||
|
Choose a folder for the future build, for example **/home/user/TBuild**. It will be named ***BuildPath*** in the rest of this document. All commands will be launched from Terminal.
|
||||||
|
|
||||||
### Obtain your API credentials
|
### Obtain your API credentials
|
||||||
|
|
||||||
You will require **api_id** and **api_hash** to access the Telegram API servers. To learn how to obtain them [click here][api_credentials].
|
You will require **api_id** and **api_hash** to access the Telegram API servers. To learn how to obtain them [click here][api_credentials].
|
||||||
|
|
||||||
### Clone source code
|
### Clone source code and prepare libraries
|
||||||
|
|
||||||
|
Install [poetry](https://python-poetry.org), go to ***BuildPath*** and run
|
||||||
|
|
||||||
git clone --recursive https://github.com/telegramdesktop/tdesktop.git
|
git clone --recursive https://github.com/telegramdesktop/tdesktop.git
|
||||||
|
./tdesktop/Telegram/build/prepare/linux.sh
|
||||||
### Prepare libraries
|
|
||||||
|
|
||||||
Install [poetry](https://python-poetry.org), go to the `tdesktop/Telegram/build/docker/centos_env` directory and run
|
|
||||||
|
|
||||||
poetry install
|
|
||||||
poetry run gen_dockerfile | DOCKER_BUILDKIT=1 docker build -t tdesktop:centos_env -
|
|
||||||
|
|
||||||
### Building the project
|
### Building the project
|
||||||
|
|
||||||
Go up to the `tdesktop` directory and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials))
|
Go to ***BuildPath*/tdesktop** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials))
|
||||||
|
|
||||||
docker run --rm -it \
|
docker run --rm -it \
|
||||||
-v $PWD:/usr/src/tdesktop \
|
-v $PWD:/usr/src/tdesktop \
|
||||||
|
|
Loading…
Add table
Reference in a new issue