mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-13 04:37:11 +02:00
Merge tag 'v5.2.2' into dev
This commit is contained in:
commit
f73edfec94
51 changed files with 408 additions and 176 deletions
|
@ -959,10 +959,10 @@ PRIVATE
|
||||||
history/history_view_highlight_manager.h
|
history/history_view_highlight_manager.h
|
||||||
history/history_widget.cpp
|
history/history_widget.cpp
|
||||||
history/history_widget.h
|
history/history_widget.h
|
||||||
info/bot/earn/info_earn_inner_widget.cpp
|
info/bot/earn/info_bot_earn_list.cpp
|
||||||
info/bot/earn/info_earn_inner_widget.h
|
info/bot/earn/info_bot_earn_list.h
|
||||||
info/bot/earn/info_earn_widget.cpp
|
info/bot/earn/info_bot_earn_widget.cpp
|
||||||
info/bot/earn/info_earn_widget.h
|
info/bot/earn/info_bot_earn_widget.h
|
||||||
info/channel_statistics/boosts/create_giveaway_box.cpp
|
info/channel_statistics/boosts/create_giveaway_box.cpp
|
||||||
info/channel_statistics/boosts/create_giveaway_box.h
|
info/channel_statistics/boosts/create_giveaway_box.h
|
||||||
info/channel_statistics/boosts/giveaway/giveaway_list_controllers.cpp
|
info/channel_statistics/boosts/giveaway/giveaway_list_controllers.cpp
|
||||||
|
@ -971,10 +971,10 @@ PRIVATE
|
||||||
info/channel_statistics/boosts/info_boosts_inner_widget.h
|
info/channel_statistics/boosts/info_boosts_inner_widget.h
|
||||||
info/channel_statistics/boosts/info_boosts_widget.cpp
|
info/channel_statistics/boosts/info_boosts_widget.cpp
|
||||||
info/channel_statistics/boosts/info_boosts_widget.h
|
info/channel_statistics/boosts/info_boosts_widget.h
|
||||||
info/channel_statistics/earn/info_earn_inner_widget.cpp
|
info/channel_statistics/earn/info_channel_earn_list.cpp
|
||||||
info/channel_statistics/earn/info_earn_inner_widget.h
|
info/channel_statistics/earn/info_channel_earn_list.h
|
||||||
info/channel_statistics/earn/info_earn_widget.cpp
|
info/channel_statistics/earn/info_channel_earn_widget.cpp
|
||||||
info/channel_statistics/earn/info_earn_widget.h
|
info/channel_statistics/earn/info_channel_earn_widget.h
|
||||||
info/common_groups/info_common_groups_inner_widget.cpp
|
info/common_groups/info_common_groups_inner_widget.cpp
|
||||||
info/common_groups/info_common_groups_inner_widget.h
|
info/common_groups/info_common_groups_inner_widget.h
|
||||||
info/common_groups/info_common_groups_widget.cpp
|
info/common_groups/info_common_groups_widget.cpp
|
||||||
|
|
BIN
Telegram/Resources/icons/menu/passcode_watch.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_watch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 438 B |
BIN
Telegram/Resources/icons/menu/passcode_watch@2x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_watch@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 631 B |
BIN
Telegram/Resources/icons/menu/passcode_watch@3x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_watch@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 886 B |
|
@ -687,6 +687,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_use_winhello_about" = "You need to enter your passcode once before unlocking Telegram with Windows Hello.";
|
"lng_settings_use_winhello_about" = "You need to enter your passcode once before unlocking Telegram with Windows Hello.";
|
||||||
"lng_settings_use_touchid" = "Unlock with Touch ID";
|
"lng_settings_use_touchid" = "Unlock with Touch ID";
|
||||||
"lng_settings_use_touchid_about" = "You need to enter your passcode once before unlocking Telegram with Touch ID.";
|
"lng_settings_use_touchid_about" = "You need to enter your passcode once before unlocking Telegram with Touch ID.";
|
||||||
|
"lng_settings_use_applewatch" = "Unlock with Apple Watch";
|
||||||
|
"lng_settings_use_applewatch_about" = "You need to enter your passcode once before unlocking Telegram with Apple Watch.";
|
||||||
|
"lng_settings_use_systempwd" = "Unlock with System Password";
|
||||||
|
"lng_settings_use_systempwd_about" = "You need to enter your passcode once before unlocking Telegram with System Password.";
|
||||||
"lng_settings_password_disable" = "Disable Cloud Password";
|
"lng_settings_password_disable" = "Disable Cloud Password";
|
||||||
"lng_settings_password_abort" = "Abort two-step verification setup";
|
"lng_settings_password_abort" = "Abort two-step verification setup";
|
||||||
"lng_settings_about_bio" = "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco";
|
"lng_settings_about_bio" = "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco";
|
||||||
|
@ -998,6 +1002,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_passcode_logout" = "Log out";
|
"lng_passcode_logout" = "Log out";
|
||||||
"lng_passcode_winhello" = "You need to enter your passcode\nbefore you can use Windows Hello.";
|
"lng_passcode_winhello" = "You need to enter your passcode\nbefore you can use Windows Hello.";
|
||||||
"lng_passcode_touchid" = "You need to enter your passcode\nbefore you can use Touch ID.";
|
"lng_passcode_touchid" = "You need to enter your passcode\nbefore you can use Touch ID.";
|
||||||
|
"lng_passcode_applewatch" = "You need to enter your passcode\nbefore you can use Watch to unlock.";
|
||||||
|
"lng_passcode_systempwd" = "You need to enter your passcode\nbefore you can use system password.";
|
||||||
"lng_passcode_winhello_unlock" = "Telegram wants to unlock with Windows Hello.";
|
"lng_passcode_winhello_unlock" = "Telegram wants to unlock with Windows Hello.";
|
||||||
"lng_passcode_touchid_unlock" = "unlock";
|
"lng_passcode_touchid_unlock" = "unlock";
|
||||||
"lng_passcode_create_button" = "Save Passcode";
|
"lng_passcode_create_button" = "Save Passcode";
|
||||||
|
|
|
@ -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="5.2.0.0" />
|
Version="5.2.2.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 5,2,0,0
|
FILEVERSION 5,2,2,0
|
||||||
PRODUCTVERSION 5,2,0,0
|
PRODUCTVERSION 5,2,2,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", "5.2.0.0"
|
VALUE "FileVersion", "5.2.2.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "5.2.0.0"
|
VALUE "ProductVersion", "5.2.2.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 5,2,0,0
|
FILEVERSION 5,2,2,0
|
||||||
PRODUCTVERSION 5,2,0,0
|
PRODUCTVERSION 5,2,2,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", "5.2.0.0"
|
VALUE "FileVersion", "5.2.2.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "5.2.0.0"
|
VALUE "ProductVersion", "5.2.2.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -293,6 +293,8 @@ passcodeSkip: 23px;
|
||||||
passcodeSystemUnlock: IconButton(defaultIconButton) {
|
passcodeSystemUnlock: IconButton(defaultIconButton) {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
icon: icon{{ "menu/passcode_winhello", lightButtonFg }};
|
||||||
|
iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }};
|
||||||
iconPosition: point(4px, 4px);
|
iconPosition: point(4px, 4px);
|
||||||
rippleAreaSize: 32px;
|
rippleAreaSize: 32px;
|
||||||
rippleAreaPosition: point(0px, 0px);
|
rippleAreaPosition: point(0px, 0px);
|
||||||
|
@ -300,14 +302,9 @@ passcodeSystemUnlock: IconButton(defaultIconButton) {
|
||||||
color: lightButtonBgOver;
|
color: lightButtonBgOver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
passcodeSystemWinHello: IconButton(passcodeSystemUnlock) {
|
passcodeSystemTouchID: icon{{ "menu/passcode_finger", lightButtonFg }};
|
||||||
icon: icon{{ "menu/passcode_winhello", lightButtonFg }};
|
passcodeSystemAppleWatch: icon{{ "menu/passcode_watch", lightButtonFg }};
|
||||||
iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }};
|
passcodeSystemSystemPwd: icon{{ "menu/permissions", lightButtonFg }};
|
||||||
}
|
|
||||||
passcodeSystemTouchID: IconButton(passcodeSystemUnlock) {
|
|
||||||
icon: icon{{ "menu/passcode_finger", lightButtonFg }};
|
|
||||||
iconOver: icon{{ "menu/passcode_finger", lightButtonFg }};
|
|
||||||
}
|
|
||||||
passcodeSystemUnlockLater: FlatLabel(defaultFlatLabel) {
|
passcodeSystemUnlockLater: FlatLabel(defaultFlatLabel) {
|
||||||
align: align(top);
|
align: align(top);
|
||||||
textFg: windowSubTextFg;
|
textFg: windowSubTextFg;
|
||||||
|
|
|
@ -43,7 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_premium_limits.h"
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "history/admin_log/history_admin_log_section.h"
|
#include "history/admin_log/history_admin_log_section.h"
|
||||||
#include "info/bot/earn/info_earn_widget.h"
|
#include "info/bot/earn/info_bot_earn_widget.h"
|
||||||
#include "info/channel_statistics/boosts/info_boosts_widget.h"
|
#include "info/channel_statistics/boosts/info_boosts_widget.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
|
@ -2200,8 +2200,11 @@ void Controller::saveForum() {
|
||||||
channel->inputChannel,
|
channel->inputChannel,
|
||||||
MTP_bool(*_savingData.forum)
|
MTP_bool(*_savingData.forum)
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
const auto weak = base::make_weak(this);
|
||||||
channel->session().api().applyUpdates(result);
|
channel->session().api().applyUpdates(result);
|
||||||
continueSave();
|
if (weak) { // todo better to be able to save in closed already box.
|
||||||
|
continueSave();
|
||||||
|
}
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
|
if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
|
||||||
continueSave();
|
continueSave();
|
||||||
|
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/battery_saving.h"
|
#include "base/battery_saving.h"
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "base/concurrent_timer.h"
|
#include "base/concurrent_timer.h"
|
||||||
|
#include "base/options.h"
|
||||||
#include "base/qt_signal_producer.h"
|
#include "base/qt_signal_producer.h"
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
|
@ -144,10 +145,18 @@ void SetCrashAnnotationsGL() {
|
||||||
#endif // DESKTOP_APP_USE_ANGLE
|
#endif // DESKTOP_APP_USE_ANGLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::options::toggle OptionSkipUrlSchemeRegister({
|
||||||
|
.id = kOptionSkipUrlSchemeRegister,
|
||||||
|
.name = "Skip URL scheme register",
|
||||||
|
.description = "Don't re-register tg:// URL scheme on autoupdate.",
|
||||||
|
});
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Application *Application::Instance = nullptr;
|
Application *Application::Instance = nullptr;
|
||||||
|
|
||||||
|
const char kOptionSkipUrlSchemeRegister[] = "skip-url-scheme-register";
|
||||||
|
|
||||||
struct Application::Private {
|
struct Application::Private {
|
||||||
base::Timer quitTimer;
|
base::Timer quitTimer;
|
||||||
UiIntegration uiIntegration;
|
UiIntegration uiIntegration;
|
||||||
|
@ -265,9 +274,14 @@ void Application::run() {
|
||||||
|
|
||||||
refreshGlobalProxy(); // Depends on app settings being read.
|
refreshGlobalProxy(); // Depends on app settings being read.
|
||||||
|
|
||||||
if (const auto old = Local::oldSettingsVersion(); old < AppVersion) {
|
if (const auto old = Local::oldSettingsVersion()) {
|
||||||
InvokeQueued(this, [] { RegisterUrlScheme(); });
|
if (old < AppVersion) {
|
||||||
Platform::NewVersionLaunched(old);
|
autoRegisterUrlScheme();
|
||||||
|
Platform::NewVersionLaunched(old);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Initial launch.
|
||||||
|
autoRegisterUrlScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cAutoStart() && !Platform::AutostartSupported()) {
|
if (cAutoStart() && !Platform::AutostartSupported()) {
|
||||||
|
@ -409,6 +423,12 @@ void Application::run() {
|
||||||
processCreatedWindow(_lastActivePrimaryWindow);
|
processCreatedWindow(_lastActivePrimaryWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::autoRegisterUrlScheme() {
|
||||||
|
if (!OptionSkipUrlSchemeRegister.value()) {
|
||||||
|
InvokeQueued(this, [] { RegisterUrlScheme(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::showAccount(not_null<Main::Account*> account) {
|
void Application::showAccount(not_null<Main::Account*> account) {
|
||||||
if (const auto separate = separateWindowFor(account)) {
|
if (const auto separate = separateWindowFor(account)) {
|
||||||
_lastActivePrimaryWindow = separate;
|
_lastActivePrimaryWindow = separate;
|
||||||
|
|
|
@ -126,6 +126,8 @@ enum class QuitReason {
|
||||||
QtQuitEvent,
|
QtQuitEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const char kOptionSkipUrlSchemeRegister[];
|
||||||
|
|
||||||
class Application final : public QObject {
|
class Application final : public QObject {
|
||||||
public:
|
public:
|
||||||
struct ProxyChange {
|
struct ProxyChange {
|
||||||
|
@ -352,6 +354,7 @@ private:
|
||||||
friend bool IsAppLaunched();
|
friend bool IsAppLaunched();
|
||||||
friend Application &App();
|
friend Application &App();
|
||||||
|
|
||||||
|
void autoRegisterUrlScheme();
|
||||||
void clearEmojiSourceImages();
|
void clearEmojiSourceImages();
|
||||||
[[nodiscard]] auto prepareEmojiSourceImages()
|
[[nodiscard]] auto prepareEmojiSourceImages()
|
||||||
-> std::shared_ptr<Ui::Emoji::UniversalImages>;
|
-> std::shared_ptr<Ui::Emoji::UniversalImages>;
|
||||||
|
|
|
@ -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 = 5002000;
|
constexpr auto AppVersion = 5002002;
|
||||||
constexpr auto AppVersionStr = "5.2";
|
constexpr auto AppVersionStr = "5.2.2";
|
||||||
constexpr auto AppBetaVersion = false;
|
constexpr auto AppBetaVersion = false;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
|
|
|
@ -3690,6 +3690,9 @@ bool InnerWidget::chooseCollapsedRow(Qt::KeyboardModifiers modifiers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::switchToFilter(FilterId filterId) {
|
void InnerWidget::switchToFilter(FilterId filterId) {
|
||||||
|
if (_controller->windowId().type != Window::SeparateType::Primary) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto &list = session().data().chatsFilters().list();
|
const auto &list = session().data().chatsFilters().list();
|
||||||
const auto filterIt = filterId
|
const auto filterIt = filterId
|
||||||
? ranges::find(list, filterId, &Data::ChatFilter::id)
|
? ranges::find(list, filterId, &Data::ChatFilter::id)
|
||||||
|
|
|
@ -100,7 +100,9 @@ ChatSearchTab SearchState::defaultTabForMe() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchState::filterChatsList() const {
|
bool SearchState::filterChatsList() const {
|
||||||
return !inChat && (tab == ChatSearchTab::MyMessages);
|
using Tab = ChatSearchTab;
|
||||||
|
return !inChat // ThisPeer can be in opened forum.
|
||||||
|
&& (tab == Tab::MyMessages || tab == Tab::ThisPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dialogs
|
} // namespace Dialogs
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
std::shared_ptr<Ui::DynamicImage> icon,
|
std::shared_ptr<Ui::DynamicImage> icon,
|
||||||
const QString &label,
|
const QString &label,
|
||||||
bool chosen);
|
bool chosen);
|
||||||
|
~Action();
|
||||||
|
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
not_null<QAction*> action() const override;
|
not_null<QAction*> action() const override;
|
||||||
|
@ -111,6 +112,10 @@ Action::Action(
|
||||||
enableMouseSelecting();
|
enableMouseSelecting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Action::~Action() {
|
||||||
|
_icon->subscribeToUpdates(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void Action::resolveMinWidth() {
|
void Action::resolveMinWidth() {
|
||||||
const auto maxWidth = st::dialogsSearchInPhotoPadding
|
const auto maxWidth = st::dialogsSearchInPhotoPadding
|
||||||
+ st::dialogsSearchInPhotoSize
|
+ st::dialogsSearchInPhotoSize
|
||||||
|
|
|
@ -1736,7 +1736,9 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
||||||
updateDragSelection(nullptr, nullptr, false);
|
updateDragSelection(nullptr, nullptr, false);
|
||||||
_selectScroll.cancel();
|
_selectScroll.cancel();
|
||||||
|
|
||||||
if (!urls.isEmpty()) mimeData->setUrls(urls);
|
if (!urls.isEmpty()) {
|
||||||
|
mimeData->setUrls(urls);
|
||||||
|
}
|
||||||
if (uponSelected && !_controller->adaptive().isOneColumn()) {
|
if (uponSelected && !_controller->adaptive().isOneColumn()) {
|
||||||
auto selectedState = getSelectionState();
|
auto selectedState = getSelectionState();
|
||||||
if (selectedState.count > 0 && selectedState.count == selectedState.canForwardCount) {
|
if (selectedState.count > 0 && selectedState.count == selectedState.canForwardCount) {
|
||||||
|
@ -1757,21 +1759,21 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
||||||
== forwardSelectionState.canForwardCount)) {
|
== forwardSelectionState.canForwardCount)) {
|
||||||
forwardIds = getSelectedItems();
|
forwardIds = getSelectedItems();
|
||||||
} else if (_mouseCursorState == CursorState::Date) {
|
} else if (_mouseCursorState == CursorState::Date) {
|
||||||
forwardIds = session().data().itemOrItsGroup(_mouseActionItem);
|
const auto item = _mouseActionItem;
|
||||||
|
if (item && item->allowsForward()) {
|
||||||
|
forwardIds = session().data().itemOrItsGroup(item);
|
||||||
|
}
|
||||||
} else if ((pressedView->isHiddenByGroup() && pressedHandler)
|
} else if ((pressedView->isHiddenByGroup() && pressedHandler)
|
||||||
|| (pressedView->media()
|
|| (pressedView->media()
|
||||||
&& pressedView->media()->dragItemByHandler(pressedHandler))) {
|
&& pressedView->media()->dragItemByHandler(pressedHandler))) {
|
||||||
const auto item = _dragStateItem
|
const auto item = _dragStateItem
|
||||||
? _dragStateItem
|
? _dragStateItem
|
||||||
: _mouseActionItem;
|
: _mouseActionItem;
|
||||||
forwardIds = MessageIdsList(1, item->fullId());
|
if (item && item->allowsForward()) {
|
||||||
|
forwardIds = MessageIdsList(1, item->fullId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (forwardIds.empty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
session().data().setMimeForwardIds(std::move(forwardIds));
|
|
||||||
auto result = std::make_unique<QMimeData>();
|
|
||||||
result->setData(u"application/x-td-forward"_q, "1");
|
|
||||||
if (pressedHandler) {
|
if (pressedHandler) {
|
||||||
const auto lnkDocument = reinterpret_cast<DocumentData*>(
|
const auto lnkDocument = reinterpret_cast<DocumentData*>(
|
||||||
pressedHandler->property(
|
pressedHandler->property(
|
||||||
|
@ -1779,12 +1781,23 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
||||||
if (lnkDocument) {
|
if (lnkDocument) {
|
||||||
const auto filepath = lnkDocument->filepath(true);
|
const auto filepath = lnkDocument->filepath(true);
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
QList<QUrl> urls;
|
|
||||||
urls.push_back(QUrl::fromLocalFile(filepath));
|
urls.push_back(QUrl::fromLocalFile(filepath));
|
||||||
result->setUrls(urls);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forwardIds.empty() && urls.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = std::make_unique<QMimeData>();
|
||||||
|
if (!forwardIds.empty()) {
|
||||||
|
session().data().setMimeForwardIds(std::move(forwardIds));
|
||||||
|
result->setData(u"application/x-td-forward"_q, "1");
|
||||||
|
}
|
||||||
|
if (!urls.isEmpty()) {
|
||||||
|
result->setUrls(urls);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -3786,12 +3786,7 @@ std::unique_ptr<QMimeData> ListWidget::prepareDrag() {
|
||||||
forwardIds = MessageIdsList(1, exactItem->fullId());
|
forwardIds = MessageIdsList(1, exactItem->fullId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (forwardIds.empty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
session().data().setMimeForwardIds(std::move(forwardIds));
|
|
||||||
auto result = std::make_unique<QMimeData>();
|
|
||||||
result->setData(u"application/x-td-forward"_q, "1");
|
|
||||||
if (pressedHandler) {
|
if (pressedHandler) {
|
||||||
const auto lnkDocument = reinterpret_cast<DocumentData*>(
|
const auto lnkDocument = reinterpret_cast<DocumentData*>(
|
||||||
pressedHandler->property(
|
pressedHandler->property(
|
||||||
|
@ -3799,12 +3794,23 @@ std::unique_ptr<QMimeData> ListWidget::prepareDrag() {
|
||||||
if (lnkDocument) {
|
if (lnkDocument) {
|
||||||
const auto filepath = lnkDocument->filepath(true);
|
const auto filepath = lnkDocument->filepath(true);
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
QList<QUrl> urls;
|
|
||||||
urls.push_back(QUrl::fromLocalFile(filepath));
|
urls.push_back(QUrl::fromLocalFile(filepath));
|
||||||
result->setUrls(urls);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forwardIds.empty() && urls.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = std::make_unique<QMimeData>();
|
||||||
|
if (!forwardIds.empty()) {
|
||||||
|
session().data().setMimeForwardIds(std::move(forwardIds));
|
||||||
|
result->setData(u"application/x-td-forward"_q, "1");
|
||||||
|
}
|
||||||
|
if (!urls.isEmpty()) {
|
||||||
|
result->setUrls(urls);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
|
||||||
For license and copyright information please follow this link:
|
For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/bot/earn/info_earn_inner_widget.h"
|
#include "info/bot/earn/info_bot_earn_list.h"
|
||||||
|
|
||||||
#include "api/api_credits.h"
|
#include "api/api_credits.h"
|
||||||
#include "api/api_filter_updates.h"
|
#include "api/api_filter_updates.h"
|
||||||
|
@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "info/bot/earn/info_earn_widget.h"
|
#include "info/bot/earn/info_bot_earn_widget.h"
|
||||||
#include "info/channel_statistics/earn/earn_format.h"
|
#include "info/channel_statistics/earn/earn_format.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
|
@ -5,9 +5,9 @@ the official desktop application for the Telegram messaging service.
|
||||||
For license and copyright information please follow this link:
|
For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/bot/earn/info_earn_widget.h"
|
#include "info/bot/earn/info_bot_earn_widget.h"
|
||||||
|
|
||||||
#include "info/bot/earn/info_earn_inner_widget.h"
|
#include "info/bot/earn/info_bot_earn_list.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
|
@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
|
||||||
For license and copyright information please follow this link:
|
For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/channel_statistics/earn/info_earn_inner_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_list.h"
|
||||||
|
|
||||||
#include "api/api_credits.h"
|
#include "api/api_credits.h"
|
||||||
#include "api/api_earn.h"
|
#include "api/api_earn.h"
|
||||||
|
@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "history/view/controls/history_view_webpage_processor.h"
|
#include "history/view/controls/history_view_webpage_processor.h"
|
||||||
#include "info/channel_statistics/earn/earn_format.h"
|
#include "info/channel_statistics/earn/earn_format.h"
|
||||||
#include "info/channel_statistics/earn/info_earn_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_widget.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
|
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
|
||||||
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
|
|
@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "info/channel_statistics/earn/info_earn_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_widget.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
|
|
|
@ -5,9 +5,9 @@ the official desktop application for the Telegram messaging service.
|
||||||
For license and copyright information please follow this link:
|
For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/channel_statistics/earn/info_earn_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_widget.h"
|
||||||
|
|
||||||
#include "info/channel_statistics/earn/info_earn_inner_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_list.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
|
@ -346,9 +346,11 @@ void Controller::createWindow() {
|
||||||
_window = std::make_unique<Ui::RpWindow>();
|
_window = std::make_unique<Ui::RpWindow>();
|
||||||
const auto window = _window.get();
|
const auto window = _window.get();
|
||||||
|
|
||||||
window->windowActiveValue(
|
base::qt_signal_producer(
|
||||||
) | rpl::filter([=](bool active) {
|
window->window()->windowHandle(),
|
||||||
return _webview && active;
|
&QWindow::activeChanged
|
||||||
|
) | rpl::filter([=] {
|
||||||
|
return _webview && window->window()->windowHandle()->isActive();
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next([=] {
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}, window->lifetime());
|
}, window->lifetime());
|
||||||
|
|
|
@ -71,6 +71,12 @@ bool Data::partial() const {
|
||||||
|
|
||||||
Data::~Data() = default;
|
Data::~Data() = default;
|
||||||
|
|
||||||
|
void Data::updateCachedViews(int cachedViews) {
|
||||||
|
_source->updatedCachedViews = std::max(
|
||||||
|
_source->updatedCachedViews,
|
||||||
|
cachedViews);
|
||||||
|
}
|
||||||
|
|
||||||
void Data::prepare(const Options &options, Fn<void(Prepared)> done) const {
|
void Data::prepare(const Options &options, Fn<void(Prepared)> done) const {
|
||||||
crl::async([source = *_source, options, done = std::move(done)] {
|
crl::async([source = *_source, options, done = std::move(done)] {
|
||||||
done(Prepare(source, options));
|
done(Prepare(source, options));
|
||||||
|
|
|
@ -45,6 +45,8 @@ public:
|
||||||
[[nodiscard]] QString id() const;
|
[[nodiscard]] QString id() const;
|
||||||
[[nodiscard]] bool partial() const;
|
[[nodiscard]] bool partial() const;
|
||||||
|
|
||||||
|
void updateCachedViews(int cachedViews);
|
||||||
|
|
||||||
void prepare(const Options &options, Fn<void(Prepared)> done) const;
|
void prepare(const Options &options, Fn<void(Prepared)> done) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -57,6 +57,7 @@ constexpr auto kGeoPointScale = 1;
|
||||||
constexpr auto kGeoPointZoomMin = 13;
|
constexpr auto kGeoPointZoomMin = 13;
|
||||||
constexpr auto kMaxLoadParts = 5;
|
constexpr auto kMaxLoadParts = 5;
|
||||||
constexpr auto kKeepLoadingParts = 8;
|
constexpr auto kKeepLoadingParts = 8;
|
||||||
|
constexpr auto kAllowPageReloadAfter = 3 * crl::time(1000);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -815,19 +816,19 @@ void Instance::show(
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::OpenPage:
|
case Type::OpenPage:
|
||||||
case Type::OpenLink:
|
case Type::OpenLink: {
|
||||||
if (!urlChecked) {
|
if (!urlChecked) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_fullRequested[_shownSession].emplace(event.url);
|
const auto session = _shownSession;
|
||||||
_shownSession->api().request(MTPmessages_GetWebPage(
|
const auto url = event.url;
|
||||||
MTP_string(event.url),
|
auto &requested = _fullRequested[session][url];
|
||||||
MTP_int(0)
|
requested.lastRequestedAt = crl::now();
|
||||||
|
session->api().request(MTPmessages_GetWebPage(
|
||||||
|
MTP_string(url),
|
||||||
|
MTP_int(requested.hash)
|
||||||
)).done([=](const MTPmessages_WebPage &result) {
|
)).done([=](const MTPmessages_WebPage &result) {
|
||||||
_shownSession->data().processUsers(result.data().vusers());
|
const auto page = processReceivedPage(session, url, result);
|
||||||
_shownSession->data().processChats(result.data().vchats());
|
|
||||||
const auto page = _shownSession->data().processWebpage(
|
|
||||||
result.data().vwebpage());
|
|
||||||
if (page && page->iv) {
|
if (page && page->iv) {
|
||||||
const auto parts = event.url.split('#');
|
const auto parts = event.url.split('#');
|
||||||
const auto hash = (parts.size() > 1) ? parts[1] : u""_q;
|
const auto hash = (parts.size() > 1) ? parts[1] : u""_q;
|
||||||
|
@ -838,7 +839,7 @@ void Instance::show(
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
UrlClickHandler::Open(event.url);
|
UrlClickHandler::Open(event.url);
|
||||||
}).send();
|
}).send();
|
||||||
break;
|
} break;
|
||||||
case Type::Report:
|
case Type::Report:
|
||||||
if (const auto controller = _shownSession->tryResolveWindow()) {
|
if (const auto controller = _shownSession->tryResolveWindow()) {
|
||||||
controller->window().activate();
|
controller->window().activate();
|
||||||
|
@ -954,15 +955,13 @@ void Instance::openWithIvPreferred(
|
||||||
};
|
};
|
||||||
_ivRequestSession = session;
|
_ivRequestSession = session;
|
||||||
_ivRequestUri = uri;
|
_ivRequestUri = uri;
|
||||||
_fullRequested[session].emplace(url);
|
auto &requested = _fullRequested[session][url];
|
||||||
|
requested.lastRequestedAt = crl::now();
|
||||||
_ivRequestId = session->api().request(MTPmessages_GetWebPage(
|
_ivRequestId = session->api().request(MTPmessages_GetWebPage(
|
||||||
MTP_string(url),
|
MTP_string(url),
|
||||||
MTP_int(0)
|
MTP_int(requested.hash)
|
||||||
)).done([=](const MTPmessages_WebPage &result) {
|
)).done([=](const MTPmessages_WebPage &result) {
|
||||||
const auto &data = result.data();
|
finish(processReceivedPage(session, url, result));
|
||||||
session->data().processUsers(data.vusers());
|
|
||||||
session->data().processChats(data.vchats());
|
|
||||||
finish(session->data().processWebpage(data.vwebpage()));
|
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
finish(nullptr);
|
finish(nullptr);
|
||||||
}).send();
|
}).send();
|
||||||
|
@ -971,24 +970,53 @@ void Instance::openWithIvPreferred(
|
||||||
void Instance::requestFull(
|
void Instance::requestFull(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QString &id) {
|
const QString &id) {
|
||||||
if (!_tracking.contains(session)
|
if (!_tracking.contains(session)) {
|
||||||
|| !_fullRequested[session].emplace(id).second) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto &requested = _fullRequested[session][id];
|
||||||
|
const auto last = requested.lastRequestedAt;
|
||||||
|
const auto now = crl::now();
|
||||||
|
if (last && (now - last) < kAllowPageReloadAfter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
requested.lastRequestedAt = now;
|
||||||
session->api().request(MTPmessages_GetWebPage(
|
session->api().request(MTPmessages_GetWebPage(
|
||||||
MTP_string(id),
|
MTP_string(id),
|
||||||
MTP_int(0)
|
MTP_int(requested.hash)
|
||||||
)).done([=](const MTPmessages_WebPage &result) {
|
)).done([=](const MTPmessages_WebPage &result) {
|
||||||
session->data().processUsers(result.data().vusers());
|
const auto page = processReceivedPage(session, id, result);
|
||||||
session->data().processChats(result.data().vchats());
|
|
||||||
const auto page = session->data().processWebpage(
|
|
||||||
result.data().vwebpage());
|
|
||||||
if (page && page->iv && _shown && _shownSession == session) {
|
if (page && page->iv && _shown && _shownSession == session) {
|
||||||
_shown->update(page->iv.get());
|
_shown->update(page->iv.get());
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPageData *Instance::processReceivedPage(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const QString &url,
|
||||||
|
const MTPmessages_WebPage &result) {
|
||||||
|
const auto &data = result.data();
|
||||||
|
const auto owner = &session->data();
|
||||||
|
owner->processUsers(data.vusers());
|
||||||
|
owner->processChats(data.vchats());
|
||||||
|
auto &requested = _fullRequested[session][url];
|
||||||
|
const auto &mtp = data.vwebpage();
|
||||||
|
mtp.match([&](const MTPDwebPageNotModified &data) {
|
||||||
|
const auto page = requested.page;
|
||||||
|
if (const auto views = data.vcached_page_views()) {
|
||||||
|
if (page && page->iv) {
|
||||||
|
page->iv->updateCachedViews(views->v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [&](const MTPDwebPage &data) {
|
||||||
|
requested.hash = data.vhash().v;
|
||||||
|
requested.page = owner->processWebpage(data).get();
|
||||||
|
}, [&](const auto &) {
|
||||||
|
requested.page = owner->processWebpage(mtp).get();
|
||||||
|
});
|
||||||
|
return requested.page;
|
||||||
|
}
|
||||||
|
|
||||||
void Instance::processOpenChannel(const QString &context) {
|
void Instance::processOpenChannel(const QString &context) {
|
||||||
if (!_shownSession) {
|
if (!_shownSession) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -61,12 +61,23 @@ public:
|
||||||
[[nodiscard]] rpl::lifetime &lifetime();
|
[[nodiscard]] rpl::lifetime &lifetime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct FullResult {
|
||||||
|
crl::time lastRequestedAt = 0;
|
||||||
|
WebPageData *page = nullptr;
|
||||||
|
int32 hash = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void processOpenChannel(const QString &context);
|
void processOpenChannel(const QString &context);
|
||||||
void processJoinChannel(const QString &context);
|
void processJoinChannel(const QString &context);
|
||||||
void requestFull(not_null<Main::Session*> session, const QString &id);
|
void requestFull(not_null<Main::Session*> session, const QString &id);
|
||||||
|
|
||||||
void trackSession(not_null<Main::Session*> session);
|
void trackSession(not_null<Main::Session*> session);
|
||||||
|
|
||||||
|
WebPageData *processReceivedPage(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const QString &url,
|
||||||
|
const MTPmessages_WebPage &result);
|
||||||
|
|
||||||
const not_null<Delegate*> _delegate;
|
const not_null<Delegate*> _delegate;
|
||||||
|
|
||||||
std::unique_ptr<Shown> _shown;
|
std::unique_ptr<Shown> _shown;
|
||||||
|
@ -77,7 +88,7 @@ private:
|
||||||
base::flat_set<not_null<ChannelData*>>> _joining;
|
base::flat_set<not_null<ChannelData*>>> _joining;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<Main::Session*>,
|
not_null<Main::Session*>,
|
||||||
base::flat_set<QString>> _fullRequested;
|
base::flat_map<QString, FullResult>> _fullRequested;
|
||||||
|
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<Main::Session*>,
|
not_null<Main::Session*>,
|
||||||
|
|
|
@ -229,7 +229,9 @@ Parser::Parser(const Source &source, const Options &options)
|
||||||
_result.name = source.name;
|
_result.name = source.name;
|
||||||
_result.rtl = source.page.data().is_rtl();
|
_result.rtl = source.page.data().is_rtl();
|
||||||
|
|
||||||
const auto views = source.page.data().vviews().value_or_empty();
|
const auto views = std::max(
|
||||||
|
source.page.data().vviews().value_or_empty(),
|
||||||
|
source.updatedCachedViews);
|
||||||
const auto content = list(source.page.data().vblocks());
|
const auto content = list(source.page.data().vblocks());
|
||||||
_result.content = wrap(content, views);
|
_result.content = wrap(content, views);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct Source {
|
||||||
std::optional<MTPPhoto> webpagePhoto;
|
std::optional<MTPPhoto> webpagePhoto;
|
||||||
std::optional<MTPDocument> webpageDocument;
|
std::optional<MTPDocument> webpageDocument;
|
||||||
QString name;
|
QString name;
|
||||||
|
int updatedCachedViews = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] Prepared Prepare(const Source &source, const Options &options);
|
[[nodiscard]] Prepared Prepare(const Source &source, const Options &options);
|
||||||
|
|
|
@ -403,6 +403,8 @@ bool Domain::removePasscodeIfEmpty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_local->setPasscode(QByteArray());
|
_local->setPasscode(QByteArray());
|
||||||
|
Core::App().settings().setSystemUnlockEnabled(false);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1193,9 +1193,11 @@ void MainWidget::setInnerFocus() {
|
||||||
_mainSection->setInnerFocus();
|
_mainSection->setInnerFocus();
|
||||||
} else if (!_hider && _thirdSection) {
|
} else if (!_hider && _thirdSection) {
|
||||||
_thirdSection->setInnerFocus();
|
_thirdSection->setInnerFocus();
|
||||||
} else {
|
} else if (_dialogs) {
|
||||||
Assert(_dialogs != nullptr);
|
|
||||||
_dialogs->setInnerFocus();
|
_dialogs->setInnerFocus();
|
||||||
|
} else {
|
||||||
|
// Maybe we're just closing a child window, content is destroyed.
|
||||||
|
_history->setFocus();
|
||||||
}
|
}
|
||||||
} else if (_mainSection) {
|
} else if (_mainSection) {
|
||||||
_mainSection->setInnerFocus();
|
_mainSection->setInnerFocus();
|
||||||
|
@ -1294,8 +1296,9 @@ void MainWidget::showHistory(
|
||||||
}
|
}
|
||||||
const auto unavailable = peer->computeUnavailableReason();
|
const auto unavailable = peer->computeUnavailableReason();
|
||||||
if (!unavailable.isEmpty()) {
|
if (!unavailable.isEmpty()) {
|
||||||
Assert(isPrimary()); // windows todo
|
if (!isPrimary()) {
|
||||||
if (params.activation != anim::activation::background) {
|
_controller->window().close();
|
||||||
|
} else if (params.activation != anim::activation::background) {
|
||||||
_controller->show(Ui::MakeInformBox(unavailable));
|
_controller->show(Ui::MakeInformBox(unavailable));
|
||||||
_controller->window().activate();
|
_controller->window().activate();
|
||||||
}
|
}
|
||||||
|
@ -1951,10 +1954,9 @@ void MainWidget::showNonPremiumLimitToast(bool download) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::showBackFromStack(
|
bool MainWidget::showBackFromStack(const SectionShow ¶ms) {
|
||||||
const SectionShow ¶ms) {
|
|
||||||
if (preventsCloseSection([=] { showBackFromStack(params); }, params)) {
|
if (preventsCloseSection([=] { showBackFromStack(params); }, params)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stack.empty()) {
|
if (_stack.empty()) {
|
||||||
|
@ -1964,7 +1966,7 @@ void MainWidget::showBackFromStack(
|
||||||
crl::on_main(this, [=] {
|
crl::on_main(this, [=] {
|
||||||
_controller->widget()->setInnerFocus();
|
_controller->widget()->setInnerFocus();
|
||||||
});
|
});
|
||||||
return;
|
return (_dialogs != nullptr);
|
||||||
}
|
}
|
||||||
auto item = std::move(_stack.back());
|
auto item = std::move(_stack.back());
|
||||||
_stack.pop_back();
|
_stack.pop_back();
|
||||||
|
@ -1996,6 +1998,7 @@ void MainWidget::showBackFromStack(
|
||||||
anim::activation::background));
|
anim::activation::background));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::orderWidgets() {
|
void MainWidget::orderWidgets() {
|
||||||
|
|
|
@ -152,8 +152,7 @@ public:
|
||||||
const SectionShow ¶ms);
|
const SectionShow ¶ms);
|
||||||
void updateColumnLayout();
|
void updateColumnLayout();
|
||||||
bool stackIsEmpty() const;
|
bool stackIsEmpty() const;
|
||||||
void showBackFromStack(
|
bool showBackFromStack(const SectionShow ¶ms);
|
||||||
const SectionShow ¶ms);
|
|
||||||
void orderWidgets();
|
void orderWidgets();
|
||||||
QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms);
|
QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms);
|
||||||
void checkMainSectionToLayer();
|
void checkMainSectionToLayer();
|
||||||
|
|
|
@ -510,15 +510,15 @@ OverlayWidget::OverlayWidget()
|
||||||
return base::EventFilterResult::Cancel;
|
return base::EventFilterResult::Cancel;
|
||||||
}
|
}
|
||||||
} else if (e->type() == QEvent::WindowStateChange) {
|
} else if (e->type() == QEvent::WindowStateChange) {
|
||||||
const auto state = _window->windowState();
|
const auto state = window()->windowState();
|
||||||
if (state & Qt::WindowMinimized || Platform::IsMac()) {
|
if (state == Qt::WindowMinimized || Platform::IsMac()) {
|
||||||
} else if (state & Qt::WindowMaximized) {
|
} else if (state == Qt::WindowMaximized) {
|
||||||
if (_fullscreen || _windowed) {
|
if (_fullscreen || _windowed) {
|
||||||
_fullscreen = _windowed = false;
|
_fullscreen = _windowed = false;
|
||||||
savePosition();
|
savePosition();
|
||||||
}
|
}
|
||||||
} else if (_fullscreen || _windowed) {
|
} else if (_fullscreen || _windowed) {
|
||||||
} else if (state & Qt::WindowFullScreen) {
|
} else if (state == Qt::WindowFullScreen) {
|
||||||
_fullscreen = true;
|
_fullscreen = true;
|
||||||
savePosition();
|
savePosition();
|
||||||
} else {
|
} else {
|
||||||
|
@ -3856,16 +3856,12 @@ void OverlayWidget::updatePowerSaveBlocker(
|
||||||
&& !IsPausedOrPausing(state.state)
|
&& !IsPausedOrPausing(state.state)
|
||||||
&& !IsStoppedOrStopping(state.state);
|
&& !IsStoppedOrStopping(state.state);
|
||||||
|
|
||||||
_window->shownValue() | rpl::filter([=](bool shown) {
|
base::UpdatePowerSaveBlocker(
|
||||||
return shown;
|
_streamed->powerSaveBlocker,
|
||||||
}) | rpl::take(1) | rpl::start_with_next([=] {
|
block,
|
||||||
base::UpdatePowerSaveBlocker(
|
base::PowerSaveBlockType::PreventDisplaySleep,
|
||||||
_streamed->powerSaveBlocker,
|
[] { return u"Video playback is active"_q; },
|
||||||
block,
|
[=] { return _window->windowHandle(); });
|
||||||
base::PowerSaveBlockType::PreventDisplaySleep,
|
|
||||||
[] { return u"Video playback is active"_q; },
|
|
||||||
[=] { return window(); });
|
|
||||||
}, lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage OverlayWidget::transformedShownContent() const {
|
QImage OverlayWidget::transformedShownContent() const {
|
||||||
|
|
|
@ -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/124.0.0.0 Safari/537.36");
|
"Chrome/126.0.0.0 Safari/537.36");
|
||||||
return kResult;
|
return kResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "platform/linux/specific_linux.h"
|
#include "platform/linux/specific_linux.h"
|
||||||
|
|
||||||
|
#include "base/openssl_help.h"
|
||||||
#include "base/random.h"
|
#include "base/random.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "base/platform/linux/base_linux_dbus_utilities.h"
|
#include "base/platform/linux/base_linux_dbus_utilities.h"
|
||||||
|
@ -480,6 +481,16 @@ void InstallLauncher() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray HashForSocketPath(const QByteArray &data) {
|
||||||
|
constexpr auto kHashForSocketPathLength = 24;
|
||||||
|
|
||||||
|
const auto binary = openssl::Sha256(bytes::make_span(data));
|
||||||
|
const auto base64 = QByteArray(
|
||||||
|
reinterpret_cast<const char*>(binary.data()),
|
||||||
|
binary.size()).toBase64(QByteArray::Base64UrlEncoding);
|
||||||
|
return base64.mid(0, kHashForSocketPathLength);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
@ -686,8 +697,8 @@ void start() {
|
||||||
|
|
||||||
Webview::WebKitGTK::SetSocketPath(u"%1/%2-%3-webview-%4"_q.arg(
|
Webview::WebKitGTK::SetSocketPath(u"%1/%2-%3-webview-%4"_q.arg(
|
||||||
QDir::tempPath(),
|
QDir::tempPath(),
|
||||||
h,
|
HashForSocketPath(d),
|
||||||
QCoreApplication::applicationName(),
|
u"TD"_q,//QCoreApplication::applicationName(), - make path smaller.
|
||||||
u"%1"_q).toStdString());
|
u"%1"_q).toStdString());
|
||||||
|
|
||||||
InstallLauncher();
|
InstallLauncher();
|
||||||
|
|
|
@ -280,10 +280,7 @@ void FillCreditOptions(
|
||||||
inner->paintRequest(
|
inner->paintRequest(
|
||||||
) | rpl::start_with_next([=](const QRect &rect) {
|
) | rpl::start_with_next([=](const QRect &rect) {
|
||||||
auto p = QPainter(inner);
|
auto p = QPainter(inner);
|
||||||
p.drawImage(
|
p.drawImage(0, 0, stars);
|
||||||
0,
|
|
||||||
(buttonHeight - stars.height()) / 2,
|
|
||||||
stars);
|
|
||||||
const auto textLeft = diffBetweenTextAndStar
|
const auto textLeft = diffBetweenTextAndStar
|
||||||
+ stars.width() / style::DevicePixelRatio();
|
+ stars.width() / style::DevicePixelRatio();
|
||||||
p.setPen(st.textFg);
|
p.setPen(st.textFg);
|
||||||
|
|
|
@ -152,6 +152,7 @@ void SetupExperimental(
|
||||||
addToggle(kOptionAutoScrollInactiveChat);
|
addToggle(kOptionAutoScrollInactiveChat);
|
||||||
addToggle(Window::Notifications::kOptionGNotification);
|
addToggle(Window::Notifications::kOptionGNotification);
|
||||||
addToggle(Core::kOptionFreeType);
|
addToggle(Core::kOptionFreeType);
|
||||||
|
addToggle(Core::kOptionSkipUrlSchemeRegister);
|
||||||
addToggle(Data::kOptionExternalVideoPlayer);
|
addToggle(Data::kOptionExternalVideoPlayer);
|
||||||
addToggle(Window::kOptionNewWindowsSizeAsFirst);
|
addToggle(Window::kOptionNewWindowsSizeAsFirst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ private:
|
||||||
rpl::event_stream<> _setInnerFocus;
|
rpl::event_stream<> _setInnerFocus;
|
||||||
rpl::event_stream<Type> _showOther;
|
rpl::event_stream<Type> _showOther;
|
||||||
rpl::event_stream<> _showBack;
|
rpl::event_stream<> _showBack;
|
||||||
|
bool _systemUnlockWithBiometric = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,6 +98,13 @@ rpl::producer<QString> LocalPasscodeEnter::title() {
|
||||||
void LocalPasscodeEnter::setupContent() {
|
void LocalPasscodeEnter::setupContent() {
|
||||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||||
|
|
||||||
|
base::SystemUnlockStatus(
|
||||||
|
true
|
||||||
|
) | rpl::start_with_next([=](base::SystemUnlockAvailability status) {
|
||||||
|
_systemUnlockWithBiometric = status.available
|
||||||
|
&& status.withBiometrics;
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
const auto isCreate = (enterType() == EnterType::Create);
|
const auto isCreate = (enterType() == EnterType::Create);
|
||||||
const auto isCheck = (enterType() == EnterType::Check);
|
const auto isCheck = (enterType() == EnterType::Check);
|
||||||
[[maybe_unused]] const auto isChange = (enterType() == EnterType::Change);
|
[[maybe_unused]] const auto isChange = (enterType() == EnterType::Change);
|
||||||
|
@ -242,8 +250,10 @@ void LocalPasscodeEnter::setupContent() {
|
||||||
}
|
}
|
||||||
SetPasscode(_controller, newText);
|
SetPasscode(_controller, newText);
|
||||||
if (isCreate) {
|
if (isCreate) {
|
||||||
Core::App().settings().setSystemUnlockEnabled(true);
|
if (Platform::IsWindows() || _systemUnlockWithBiometric) {
|
||||||
Core::App().saveSettingsDelayed();
|
Core::App().settings().setSystemUnlockEnabled(true);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
|
}
|
||||||
_showOther.fire(LocalPasscodeManageId());
|
_showOther.fire(LocalPasscodeManageId());
|
||||||
} else if (isChange) {
|
} else if (isChange) {
|
||||||
_showBack.fire({});
|
_showBack.fire({});
|
||||||
|
@ -518,38 +528,77 @@ void LocalPasscodeManage::setupContent() {
|
||||||
)->setDuration(0);
|
)->setDuration(0);
|
||||||
const auto systemUnlockContent = systemUnlockWrap->entity();
|
const auto systemUnlockContent = systemUnlockWrap->entity();
|
||||||
|
|
||||||
Ui::AddSkip(systemUnlockContent);
|
enum class UnlockType {
|
||||||
|
None,
|
||||||
|
Default,
|
||||||
|
Biometrics,
|
||||||
|
Companion,
|
||||||
|
};
|
||||||
|
const auto unlockType = systemUnlockContent->lifetime().make_state<
|
||||||
|
rpl::variable<UnlockType>
|
||||||
|
>(base::SystemUnlockStatus(
|
||||||
|
true
|
||||||
|
) | rpl::map([](base::SystemUnlockAvailability status) {
|
||||||
|
return status.withBiometrics
|
||||||
|
? UnlockType::Biometrics
|
||||||
|
: status.withCompanion
|
||||||
|
? UnlockType::Companion
|
||||||
|
: status.available
|
||||||
|
? UnlockType::Default
|
||||||
|
: UnlockType::None;
|
||||||
|
}));
|
||||||
|
|
||||||
|
unlockType->value(
|
||||||
|
) | rpl::start_with_next([=](UnlockType type) {
|
||||||
|
while (systemUnlockContent->count()) {
|
||||||
|
delete systemUnlockContent->widgetAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ui::AddSkip(systemUnlockContent);
|
||||||
|
|
||||||
|
AddButtonWithIcon(
|
||||||
|
systemUnlockContent,
|
||||||
|
(Platform::IsWindows()
|
||||||
|
? tr::lng_settings_use_winhello()
|
||||||
|
: (type == UnlockType::Biometrics)
|
||||||
|
? tr::lng_settings_use_touchid()
|
||||||
|
: (type == UnlockType::Companion)
|
||||||
|
? tr::lng_settings_use_applewatch()
|
||||||
|
: tr::lng_settings_use_systempwd()),
|
||||||
|
st::settingsButton,
|
||||||
|
{ Platform::IsWindows()
|
||||||
|
? &st::menuIconWinHello
|
||||||
|
: (type == UnlockType::Biometrics)
|
||||||
|
? &st::menuIconTouchID
|
||||||
|
: (type == UnlockType::Companion)
|
||||||
|
? &st::menuIconAppleWatch
|
||||||
|
: &st::menuIconSystemPwd }
|
||||||
|
)->toggleOn(
|
||||||
|
rpl::single(Core::App().settings().systemUnlockEnabled())
|
||||||
|
)->toggledChanges(
|
||||||
|
) | rpl::filter([=](bool value) {
|
||||||
|
return value != Core::App().settings().systemUnlockEnabled();
|
||||||
|
}) | rpl::start_with_next([=](bool value) {
|
||||||
|
Core::App().settings().setSystemUnlockEnabled(value);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
|
}, systemUnlockContent->lifetime());
|
||||||
|
|
||||||
|
Ui::AddSkip(systemUnlockContent);
|
||||||
|
|
||||||
|
Ui::AddDividerText(
|
||||||
|
systemUnlockContent,
|
||||||
|
(Platform::IsWindows()
|
||||||
|
? tr::lng_settings_use_winhello_about()
|
||||||
|
: (type == UnlockType::Biometrics)
|
||||||
|
? tr::lng_settings_use_touchid_about()
|
||||||
|
: (type == UnlockType::Companion)
|
||||||
|
? tr::lng_settings_use_applewatch_about()
|
||||||
|
: tr::lng_settings_use_systempwd_about()));
|
||||||
|
|
||||||
AddButtonWithIcon(
|
|
||||||
systemUnlockContent,
|
|
||||||
(Platform::IsWindows()
|
|
||||||
? tr::lng_settings_use_winhello()
|
|
||||||
: tr::lng_settings_use_touchid()),
|
|
||||||
st::settingsButton,
|
|
||||||
{ Platform::IsWindows()
|
|
||||||
? &st::menuIconWinHello
|
|
||||||
: &st::menuIconTouchID }
|
|
||||||
)->toggleOn(
|
|
||||||
rpl::single(Core::App().settings().systemUnlockEnabled())
|
|
||||||
)->toggledChanges(
|
|
||||||
) | rpl::filter([=](bool value) {
|
|
||||||
return value != Core::App().settings().systemUnlockEnabled();
|
|
||||||
}) | rpl::start_with_next([=](bool value) {
|
|
||||||
Core::App().settings().setSystemUnlockEnabled(value);
|
|
||||||
Core::App().saveSettingsDelayed();
|
|
||||||
}, systemUnlockContent->lifetime());
|
}, systemUnlockContent->lifetime());
|
||||||
|
|
||||||
Ui::AddSkip(systemUnlockContent);
|
systemUnlockWrap->toggleOn(unlockType->value(
|
||||||
|
) | rpl::map(rpl::mappers::_1 != UnlockType::None));
|
||||||
Ui::AddDividerText(
|
|
||||||
systemUnlockContent,
|
|
||||||
(Platform::IsWindows()
|
|
||||||
? tr::lng_settings_use_winhello_about()
|
|
||||||
: tr::lng_settings_use_touchid_about()));
|
|
||||||
|
|
||||||
using namespace rpl::mappers;
|
|
||||||
systemUnlockWrap->toggleOn(base::SystemUnlockStatus(
|
|
||||||
) | rpl::map(_1 == base::SystemUnlockAvailability::Available));
|
|
||||||
|
|
||||||
Ui::ResizeFitChild(this, content);
|
Ui::ResizeFitChild(this, content);
|
||||||
}
|
}
|
||||||
|
@ -562,6 +611,8 @@ QPointer<Ui::RpWidget> LocalPasscodeManage::createPinnedToBottom(
|
||||||
.text = tr::lng_settings_passcode_disable_sure(),
|
.text = tr::lng_settings_passcode_disable_sure(),
|
||||||
.confirmed = [=](Fn<void()> &&close) {
|
.confirmed = [=](Fn<void()> &&close) {
|
||||||
SetPasscode(_controller, QString());
|
SetPasscode(_controller, QString());
|
||||||
|
Core::App().settings().setSystemUnlockEnabled(false);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
|
|
||||||
close();
|
close();
|
||||||
_showBack.fire({});
|
_showBack.fire({});
|
||||||
|
|
|
@ -157,6 +157,8 @@ menuIconFont: icon {{ "menu/fonts", menuIconColor }};
|
||||||
menuIconFactcheck: icon {{ "menu/factcheck", menuIconColor }};
|
menuIconFactcheck: icon {{ "menu/factcheck", menuIconColor }};
|
||||||
menuIconWinHello: icon {{ "menu/passcode_winhello", menuIconColor }};
|
menuIconWinHello: icon {{ "menu/passcode_winhello", menuIconColor }};
|
||||||
menuIconTouchID: icon {{ "menu/passcode_finger", menuIconColor }};
|
menuIconTouchID: icon {{ "menu/passcode_finger", menuIconColor }};
|
||||||
|
menuIconAppleWatch: icon {{ "menu/passcode_watch", menuIconColor }};
|
||||||
|
menuIconSystemPwd: menuIconPermissions;
|
||||||
|
|
||||||
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
|
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
|
||||||
menuIconTTLAnyTextPosition: point(11px, 22px);
|
menuIconTTLAnyTextPosition: point(11px, 22px);
|
||||||
|
|
|
@ -110,8 +110,17 @@ PasscodeLockWidget::PasscodeLockWidget(
|
||||||
|
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
if (Core::App().settings().systemUnlockEnabled()) {
|
if (Core::App().settings().systemUnlockEnabled()) {
|
||||||
_systemUnlockAvailable = base::SystemUnlockStatus()
|
_systemUnlockAvailable = base::SystemUnlockStatus(
|
||||||
| rpl::map(_1 == base::SystemUnlockAvailability::Available);
|
true
|
||||||
|
) | rpl::map([](base::SystemUnlockAvailability status) {
|
||||||
|
return status.withBiometrics
|
||||||
|
? SystemUnlockType::Biometrics
|
||||||
|
: status.withCompanion
|
||||||
|
? SystemUnlockType::Companion
|
||||||
|
: status.available
|
||||||
|
? SystemUnlockType::Default
|
||||||
|
: SystemUnlockType::None;
|
||||||
|
});
|
||||||
if (Core::App().domain().started()) {
|
if (Core::App().domain().started()) {
|
||||||
_systemUnlockAllowed = _systemUnlockAvailable.value();
|
_systemUnlockAllowed = _systemUnlockAvailable.value();
|
||||||
setupSystemUnlock();
|
setupSystemUnlock();
|
||||||
|
@ -122,11 +131,22 @@ PasscodeLockWidget::PasscodeLockWidget(
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasscodeLockWidget::setupSystemUnlockInfo() {
|
void PasscodeLockWidget::setupSystemUnlockInfo() {
|
||||||
|
const auto macos = [&] {
|
||||||
|
return _systemUnlockAvailable.value(
|
||||||
|
) | rpl::map([](SystemUnlockType type) {
|
||||||
|
return (type == SystemUnlockType::Biometrics)
|
||||||
|
? tr::lng_passcode_touchid()
|
||||||
|
: (type == SystemUnlockType::Companion)
|
||||||
|
? tr::lng_passcode_applewatch()
|
||||||
|
: tr::lng_passcode_systempwd();
|
||||||
|
}) | rpl::flatten_latest();
|
||||||
|
};
|
||||||
|
auto text = Platform::IsWindows()
|
||||||
|
? tr::lng_passcode_winhello()
|
||||||
|
: macos();
|
||||||
const auto info = Ui::CreateChild<Ui::FlatLabel>(
|
const auto info = Ui::CreateChild<Ui::FlatLabel>(
|
||||||
this,
|
this,
|
||||||
(Platform::IsWindows()
|
std::move(text),
|
||||||
? tr::lng_passcode_winhello()
|
|
||||||
: tr::lng_passcode_touchid()),
|
|
||||||
st::passcodeSystemUnlockLater);
|
st::passcodeSystemUnlockLater);
|
||||||
_logout->geometryValue(
|
_logout->geometryValue(
|
||||||
) | rpl::start_with_next([=](QRect logout) {
|
) | rpl::start_with_next([=](QRect logout) {
|
||||||
|
@ -137,7 +157,8 @@ void PasscodeLockWidget::setupSystemUnlockInfo() {
|
||||||
st::boxRowPadding.left(),
|
st::boxRowPadding.left(),
|
||||||
logout.y() + logout.height() + st::passcodeSystemUnlockSkip);
|
logout.y() + logout.height() + st::passcodeSystemUnlockSkip);
|
||||||
}, info->lifetime());
|
}, info->lifetime());
|
||||||
info->showOn(_systemUnlockAvailable.value());
|
info->showOn(_systemUnlockAvailable.value(
|
||||||
|
) | rpl::map(rpl::mappers::_1 != SystemUnlockType::None));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasscodeLockWidget::setupSystemUnlock() {
|
void PasscodeLockWidget::setupSystemUnlock() {
|
||||||
|
@ -152,10 +173,21 @@ void PasscodeLockWidget::setupSystemUnlock() {
|
||||||
|
|
||||||
const auto button = Ui::CreateChild<Ui::IconButton>(
|
const auto button = Ui::CreateChild<Ui::IconButton>(
|
||||||
_passcode.data(),
|
_passcode.data(),
|
||||||
(Platform::IsWindows()
|
st::passcodeSystemUnlock);
|
||||||
? st::passcodeSystemWinHello
|
if (!Platform::IsWindows()) {
|
||||||
: st::passcodeSystemTouchID));
|
using namespace base;
|
||||||
button->showOn(_systemUnlockAllowed.value());
|
_systemUnlockAllowed.value(
|
||||||
|
) | rpl::start_with_next([=](SystemUnlockType type) {
|
||||||
|
const auto icon = (type == SystemUnlockType::Biometrics)
|
||||||
|
? &st::passcodeSystemTouchID
|
||||||
|
: (type == SystemUnlockType::Companion)
|
||||||
|
? &st::passcodeSystemAppleWatch
|
||||||
|
: &st::passcodeSystemSystemPwd;
|
||||||
|
button->setIconOverride(icon, icon);
|
||||||
|
}, button->lifetime());
|
||||||
|
}
|
||||||
|
button->showOn(_systemUnlockAllowed.value(
|
||||||
|
) | rpl::map(rpl::mappers::_1 != SystemUnlockType::None));
|
||||||
_passcode->sizeValue() | rpl::start_with_next([=](QSize size) {
|
_passcode->sizeValue() | rpl::start_with_next([=](QSize size) {
|
||||||
button->moveToRight(0, size.height() - button->height());
|
button->moveToRight(0, size.height() - button->height());
|
||||||
}, button->lifetime());
|
}, button->lifetime());
|
||||||
|
@ -177,7 +209,7 @@ void PasscodeLockWidget::suggestSystemUnlock() {
|
||||||
using namespace base;
|
using namespace base;
|
||||||
_systemUnlockAllowed.value(
|
_systemUnlockAllowed.value(
|
||||||
) | rpl::filter(
|
) | rpl::filter(
|
||||||
rpl::mappers::_1
|
rpl::mappers::_1 != SystemUnlockType::None
|
||||||
) | rpl::take(1) | rpl::start_with_next([=] {
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
const auto weak = Ui::MakeWeak(this);
|
const auto weak = Ui::MakeWeak(this);
|
||||||
const auto done = [weak](SystemUnlockResult result) {
|
const auto done = [weak](SystemUnlockResult result) {
|
||||||
|
|
|
@ -65,6 +65,13 @@ protected:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class SystemUnlockType : uchar {
|
||||||
|
None,
|
||||||
|
Default,
|
||||||
|
Biometrics,
|
||||||
|
Companion,
|
||||||
|
};
|
||||||
|
|
||||||
void paintContent(QPainter &p) override;
|
void paintContent(QPainter &p) override;
|
||||||
|
|
||||||
void setupSystemUnlockInfo();
|
void setupSystemUnlockInfo();
|
||||||
|
@ -75,8 +82,8 @@ private:
|
||||||
void submit();
|
void submit();
|
||||||
void error();
|
void error();
|
||||||
|
|
||||||
rpl::variable<bool> _systemUnlockAvailable = false;
|
rpl::variable<SystemUnlockType> _systemUnlockAvailable;
|
||||||
rpl::variable<bool> _systemUnlockAllowed = false;
|
rpl::variable<SystemUnlockType> _systemUnlockAllowed;
|
||||||
object_ptr<Ui::PasswordInput> _passcode;
|
object_ptr<Ui::PasswordInput> _passcode;
|
||||||
object_ptr<Ui::RoundButton> _submit;
|
object_ptr<Ui::RoundButton> _submit;
|
||||||
object_ptr<Ui::LinkButton> _logout;
|
object_ptr<Ui::LinkButton> _logout;
|
||||||
|
|
|
@ -67,7 +67,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
#include "info/channel_statistics/boosts/info_boosts_widget.h"
|
#include "info/channel_statistics/boosts/info_boosts_widget.h"
|
||||||
#include "info/channel_statistics/earn/info_earn_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_widget.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "info/statistics/info_statistics_widget.h"
|
#include "info/statistics/info_statistics_widget.h"
|
||||||
#include "info/stories/info_stories_widget.h"
|
#include "info/stories/info_stories_widget.h"
|
||||||
|
@ -694,8 +694,9 @@ void Filler::addNewWindow() {
|
||||||
_addAction(tr::lng_context_new_window(tr::now), [=] {
|
_addAction(tr::lng_context_new_window(tr::now), [=] {
|
||||||
Ui::PreventDelayedActivation();
|
Ui::PreventDelayedActivation();
|
||||||
if (const auto strong = weak.get()) {
|
if (const auto strong = weak.get()) {
|
||||||
|
const auto forum = !strong->asTopic() && peer->isForum();
|
||||||
controller->showInNewWindow(SeparateId(
|
controller->showInNewWindow(SeparateId(
|
||||||
peer->isForum() ? SeparateType::Forum : SeparateType::Chat,
|
forum ? SeparateType::Forum : SeparateType::Chat,
|
||||||
strong));
|
strong));
|
||||||
}
|
}
|
||||||
}, &st::menuIconNewWindow);
|
}, &st::menuIconNewWindow);
|
||||||
|
|
|
@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_filters_menu.h"
|
#include "window/window_filters_menu.h"
|
||||||
#include "window/window_separate_id.h"
|
#include "window/window_separate_id.h"
|
||||||
#include "info/channel_statistics/earn/info_earn_inner_widget.h"
|
#include "info/channel_statistics/earn/info_channel_earn_list.h"
|
||||||
#include "info/info_memento.h"
|
#include "info/info_memento.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "inline_bots/bot_attach_web_view.h"
|
#include "inline_bots/bot_attach_web_view.h"
|
||||||
|
@ -1668,8 +1668,9 @@ void SessionController::showForum(
|
||||||
) | rpl::start_with_next([=, history = forum->history()] {
|
) | rpl::start_with_next([=, history = forum->history()] {
|
||||||
const auto now = activeChatCurrent().owningHistory();
|
const auto now = activeChatCurrent().owningHistory();
|
||||||
const auto showHistory = !now || (now == history);
|
const auto showHistory = !now || (now == history);
|
||||||
|
const auto weak = base::make_weak(this);
|
||||||
closeForum();
|
closeForum();
|
||||||
if (showHistory) {
|
if (weak && showHistory) {
|
||||||
showPeerHistory(history, {
|
showPeerHistory(history, {
|
||||||
SectionShow::Way::Backward,
|
SectionShow::Way::Backward,
|
||||||
anim::type::normal,
|
anim::type::normal,
|
||||||
|
@ -1684,7 +1685,7 @@ void SessionController::closeForum() {
|
||||||
if (const auto forum = _shownForum.current()) {
|
if (const auto forum = _shownForum.current()) {
|
||||||
const auto id = windowId();
|
const auto id = windowId();
|
||||||
if (id.type == SeparateType::Forum) {
|
if (id.type == SeparateType::Forum) {
|
||||||
const auto initial = id.thread->asForum();
|
const auto initial = id.forum();
|
||||||
if (!initial || initial == forum) {
|
if (!initial || initial == forum) {
|
||||||
Core::App().closeWindow(_window);
|
Core::App().closeWindow(_window);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2537,7 +2538,13 @@ void SessionController::showBackFromStack(const SectionShow ¶ms) {
|
||||||
return topic && topic->forum()->topicDeleted(topic->rootId());
|
return topic && topic->forum()->topicDeleted(topic->rootId());
|
||||||
};
|
};
|
||||||
do {
|
do {
|
||||||
content()->showBackFromStack(params);
|
const auto empty = content()->stackIsEmpty();
|
||||||
|
const auto shown = content()->showBackFromStack(params);
|
||||||
|
if (empty && !shown && content()->stackIsEmpty() && bad()) {
|
||||||
|
clearSectionStack(anim::type::instant);
|
||||||
|
window().close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
} while (bad());
|
} while (bad());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
AppVersion 5002000
|
AppVersion 5002002
|
||||||
AppVersionStrMajor 5.2
|
AppVersionStrMajor 5.2
|
||||||
AppVersionStrSmall 5.2
|
AppVersionStrSmall 5.2.2
|
||||||
AppVersionStr 5.2.0
|
AppVersionStr 5.2.2
|
||||||
BetaChannel 0
|
BetaChannel 0
|
||||||
AlphaVersion 0
|
AlphaVersion 0
|
||||||
AppVersionOriginal 5.2
|
AppVersionOriginal 5.2.2
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b512eead302cb7b509869778348d60fef64bc19b
|
Subproject commit f30400147d997fedc787e214467d305db6c159e7
|
|
@ -1 +1 @@
|
||||||
Subproject commit 59d92261783ae403e8708f972c36be3d21ab064d
|
Subproject commit 0b7622ff38778e9cd03d3997de59351973480a1f
|
|
@ -1,3 +1,16 @@
|
||||||
|
5.2.2 (02.07.24)
|
||||||
|
|
||||||
|
- Fix topics search in topic groups.
|
||||||
|
- Fix Instant View pages content updating.
|
||||||
|
|
||||||
|
5.2.1 (01.07.24)
|
||||||
|
|
||||||
|
- Fix crash when opening topic in a new window.
|
||||||
|
- Fix crash in topic search scope dropdown.
|
||||||
|
- Fix crash in video player.
|
||||||
|
- Fix feeze and crash in Instant View (Windows).
|
||||||
|
- Allow unlock by Apple Watch or System Password (macOS).
|
||||||
|
|
||||||
5.2 (30.06.24)
|
5.2 (30.06.24)
|
||||||
|
|
||||||
- Pay for content with Telegram Stars.
|
- Pay for content with Telegram Stars.
|
||||||
|
|
Loading…
Add table
Reference in a new issue