diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 0bd3e89cc..c4dc6043d 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -959,10 +959,10 @@ PRIVATE history/history_view_highlight_manager.h history/history_widget.cpp history/history_widget.h - info/bot/earn/info_earn_inner_widget.cpp - info/bot/earn/info_earn_inner_widget.h - info/bot/earn/info_earn_widget.cpp - info/bot/earn/info_earn_widget.h + info/bot/earn/info_bot_earn_list.cpp + info/bot/earn/info_bot_earn_list.h + info/bot/earn/info_bot_earn_widget.cpp + info/bot/earn/info_bot_earn_widget.h info/channel_statistics/boosts/create_giveaway_box.cpp info/channel_statistics/boosts/create_giveaway_box.h 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_widget.cpp info/channel_statistics/boosts/info_boosts_widget.h - info/channel_statistics/earn/info_earn_inner_widget.cpp - info/channel_statistics/earn/info_earn_inner_widget.h - info/channel_statistics/earn/info_earn_widget.cpp - info/channel_statistics/earn/info_earn_widget.h + info/channel_statistics/earn/info_channel_earn_list.cpp + info/channel_statistics/earn/info_channel_earn_list.h + info/channel_statistics/earn/info_channel_earn_widget.cpp + 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.h info/common_groups/info_common_groups_widget.cpp diff --git a/Telegram/Resources/icons/menu/passcode_watch.png b/Telegram/Resources/icons/menu/passcode_watch.png new file mode 100644 index 000000000..161da4e87 Binary files /dev/null and b/Telegram/Resources/icons/menu/passcode_watch.png differ diff --git a/Telegram/Resources/icons/menu/passcode_watch@2x.png b/Telegram/Resources/icons/menu/passcode_watch@2x.png new file mode 100644 index 000000000..516e313b7 Binary files /dev/null and b/Telegram/Resources/icons/menu/passcode_watch@2x.png differ diff --git a/Telegram/Resources/icons/menu/passcode_watch@3x.png b/Telegram/Resources/icons/menu/passcode_watch@3x.png new file mode 100644 index 000000000..2b5f71f72 Binary files /dev/null and b/Telegram/Resources/icons/menu/passcode_watch@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3a05b3558..9213a3203 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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_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_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_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"; @@ -998,6 +1002,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_passcode_logout" = "Log out"; "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_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_touchid_unlock" = "unlock"; "lng_passcode_create_button" = "Save Passcode"; diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 6358fd7a8..53203464b 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -10,7 +10,7 @@ + Version="5.2.2.0" /> Telegram Desktop Telegram Messenger LLP diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index a0add328c..ae26d7f19 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 5,2,0,0 - PRODUCTVERSION 5,2,0,0 + FILEVERSION 5,2,2,0 + PRODUCTVERSION 5,2,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Radolyn Labs" VALUE "FileDescription", "AyuGram Desktop" - VALUE "FileVersion", "5.2.0.0" + VALUE "FileVersion", "5.2.2.0" VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "ProductName", "AyuGram Desktop" - VALUE "ProductVersion", "5.2.0.0" + VALUE "ProductVersion", "5.2.2.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index f4d9012ed..5fb0f2a20 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 5,2,0,0 - PRODUCTVERSION 5,2,0,0 + FILEVERSION 5,2,2,0 + PRODUCTVERSION 5,2,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -53,10 +53,10 @@ BEGIN BEGIN VALUE "CompanyName", "Radolyn Labs" VALUE "FileDescription", "AyuGram Desktop Updater" - VALUE "FileVersion", "5.2.0.0" + VALUE "FileVersion", "5.2.2.0" VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "ProductName", "AyuGram Desktop" - VALUE "ProductVersion", "5.2.0.0" + VALUE "ProductVersion", "5.2.2.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 096adc10d..c549948e0 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -293,6 +293,8 @@ passcodeSkip: 23px; passcodeSystemUnlock: IconButton(defaultIconButton) { width: 32px; height: 36px; + icon: icon{{ "menu/passcode_winhello", lightButtonFg }}; + iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }}; iconPosition: point(4px, 4px); rippleAreaSize: 32px; rippleAreaPosition: point(0px, 0px); @@ -300,14 +302,9 @@ passcodeSystemUnlock: IconButton(defaultIconButton) { color: lightButtonBgOver; } } -passcodeSystemWinHello: IconButton(passcodeSystemUnlock) { - icon: icon{{ "menu/passcode_winhello", lightButtonFg }}; - iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }}; -} -passcodeSystemTouchID: IconButton(passcodeSystemUnlock) { - icon: icon{{ "menu/passcode_finger", lightButtonFg }}; - iconOver: icon{{ "menu/passcode_finger", lightButtonFg }}; -} +passcodeSystemTouchID: icon{{ "menu/passcode_finger", lightButtonFg }}; +passcodeSystemAppleWatch: icon{{ "menu/passcode_watch", lightButtonFg }}; +passcodeSystemSystemPwd: icon{{ "menu/permissions", lightButtonFg }}; passcodeSystemUnlockLater: FlatLabel(defaultFlatLabel) { align: align(top); textFg: windowSubTextFg; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 5623bea94..0ba6354f9 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -43,7 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_premium_limits.h" #include "data/data_user.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/profile/info_profile_values.h" #include "info/info_memento.h" @@ -2200,8 +2200,11 @@ void Controller::saveForum() { channel->inputChannel, MTP_bool(*_savingData.forum) )).done([=](const MTPUpdates &result) { + const auto weak = base::make_weak(this); 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) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) { continueSave(); diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index db9a85b88..4540e704b 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/battery_saving.h" #include "base/event_filter.h" #include "base/concurrent_timer.h" +#include "base/options.h" #include "base/qt_signal_producer.h" #include "base/timer.h" #include "base/unixtime.h" @@ -144,10 +145,18 @@ void SetCrashAnnotationsGL() { #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 Application *Application::Instance = nullptr; +const char kOptionSkipUrlSchemeRegister[] = "skip-url-scheme-register"; + struct Application::Private { base::Timer quitTimer; UiIntegration uiIntegration; @@ -265,9 +274,14 @@ void Application::run() { refreshGlobalProxy(); // Depends on app settings being read. - if (const auto old = Local::oldSettingsVersion(); old < AppVersion) { - InvokeQueued(this, [] { RegisterUrlScheme(); }); - Platform::NewVersionLaunched(old); + if (const auto old = Local::oldSettingsVersion()) { + if (old < AppVersion) { + autoRegisterUrlScheme(); + Platform::NewVersionLaunched(old); + } + } else { + // Initial launch. + autoRegisterUrlScheme(); } if (cAutoStart() && !Platform::AutostartSupported()) { @@ -409,6 +423,12 @@ void Application::run() { processCreatedWindow(_lastActivePrimaryWindow); } +void Application::autoRegisterUrlScheme() { + if (!OptionSkipUrlSchemeRegister.value()) { + InvokeQueued(this, [] { RegisterUrlScheme(); }); + } +} + void Application::showAccount(not_null account) { if (const auto separate = separateWindowFor(account)) { _lastActivePrimaryWindow = separate; diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index 28975d474..e73878ef2 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -126,6 +126,8 @@ enum class QuitReason { QtQuitEvent, }; +extern const char kOptionSkipUrlSchemeRegister[]; + class Application final : public QObject { public: struct ProxyChange { @@ -352,6 +354,7 @@ private: friend bool IsAppLaunched(); friend Application &App(); + void autoRegisterUrlScheme(); void clearEmojiSourceImages(); [[nodiscard]] auto prepareEmojiSourceImages() -> std::shared_ptr; diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index b3a93d830..5db1682b1 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs; constexpr auto AppNameOld = "AyuGram for Windows"_cs; constexpr auto AppName = "AyuGram Desktop"_cs; constexpr auto AppFile = "AyuGram"_cs; -constexpr auto AppVersion = 5002000; -constexpr auto AppVersionStr = "5.2"; +constexpr auto AppVersion = 5002002; +constexpr auto AppVersionStr = "5.2.2"; constexpr auto AppBetaVersion = false; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 1ac569e9c..cb33e8a9a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -3690,6 +3690,9 @@ bool InnerWidget::chooseCollapsedRow(Qt::KeyboardModifiers modifiers) { } void InnerWidget::switchToFilter(FilterId filterId) { + if (_controller->windowId().type != Window::SeparateType::Primary) { + return; + } const auto &list = session().data().chatsFilters().list(); const auto filterIt = filterId ? ranges::find(list, filterId, &Data::ChatFilter::id) diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.cpp b/Telegram/SourceFiles/dialogs/dialogs_key.cpp index 544c48cca..db5df9627 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_key.cpp @@ -100,7 +100,9 @@ ChatSearchTab SearchState::defaultTabForMe() 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 diff --git a/Telegram/SourceFiles/dialogs/ui/chat_search_in.cpp b/Telegram/SourceFiles/dialogs/ui/chat_search_in.cpp index 5fcc8f78b..42e8c33d7 100644 --- a/Telegram/SourceFiles/dialogs/ui/chat_search_in.cpp +++ b/Telegram/SourceFiles/dialogs/ui/chat_search_in.cpp @@ -29,6 +29,7 @@ public: std::shared_ptr icon, const QString &label, bool chosen); + ~Action(); bool isEnabled() const override; not_null action() const override; @@ -111,6 +112,10 @@ Action::Action( enableMouseSelecting(); } +Action::~Action() { + _icon->subscribeToUpdates(nullptr); +} + void Action::resolveMinWidth() { const auto maxWidth = st::dialogsSearchInPhotoPadding + st::dialogsSearchInPhotoSize diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 5be5fb12d..094e99221 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1736,7 +1736,9 @@ std::unique_ptr HistoryInner::prepareDrag() { updateDragSelection(nullptr, nullptr, false); _selectScroll.cancel(); - if (!urls.isEmpty()) mimeData->setUrls(urls); + if (!urls.isEmpty()) { + mimeData->setUrls(urls); + } if (uponSelected && !_controller->adaptive().isOneColumn()) { auto selectedState = getSelectionState(); if (selectedState.count > 0 && selectedState.count == selectedState.canForwardCount) { @@ -1757,21 +1759,21 @@ std::unique_ptr HistoryInner::prepareDrag() { == forwardSelectionState.canForwardCount)) { forwardIds = getSelectedItems(); } 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) || (pressedView->media() && pressedView->media()->dragItemByHandler(pressedHandler))) { const auto item = _dragStateItem ? _dragStateItem : _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(); - result->setData(u"application/x-td-forward"_q, "1"); + if (pressedHandler) { const auto lnkDocument = reinterpret_cast( pressedHandler->property( @@ -1779,12 +1781,23 @@ std::unique_ptr HistoryInner::prepareDrag() { if (lnkDocument) { const auto filepath = lnkDocument->filepath(true); if (!filepath.isEmpty()) { - QList urls; urls.push_back(QUrl::fromLocalFile(filepath)); - result->setUrls(urls); } } } + + if (forwardIds.empty() && urls.isEmpty()) { + return nullptr; + } + + auto result = std::make_unique(); + 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 nullptr; diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 7f4392202..0f6d808b5 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -3786,12 +3786,7 @@ std::unique_ptr ListWidget::prepareDrag() { forwardIds = MessageIdsList(1, exactItem->fullId()); } } - if (forwardIds.empty()) { - return nullptr; - } - session().data().setMimeForwardIds(std::move(forwardIds)); - auto result = std::make_unique(); - result->setData(u"application/x-td-forward"_q, "1"); + if (pressedHandler) { const auto lnkDocument = reinterpret_cast( pressedHandler->property( @@ -3799,12 +3794,23 @@ std::unique_ptr ListWidget::prepareDrag() { if (lnkDocument) { const auto filepath = lnkDocument->filepath(true); if (!filepath.isEmpty()) { - QList urls; urls.push_back(QUrl::fromLocalFile(filepath)); - result->setUrls(urls); } } } + + if (forwardIds.empty() && urls.isEmpty()) { + return nullptr; + } + + auto result = std::make_unique(); + 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 nullptr; diff --git a/Telegram/SourceFiles/info/bot/earn/info_earn_inner_widget.cpp b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_list.cpp similarity index 99% rename from Telegram/SourceFiles/info/bot/earn/info_earn_inner_widget.cpp rename to Telegram/SourceFiles/info/bot/earn/info_bot_earn_list.cpp index 2b152ad6f..169fe8883 100644 --- a/Telegram/SourceFiles/info/bot/earn/info_earn_inner_widget.cpp +++ b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_list.cpp @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "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_filter_updates.h" @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_user.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/info_controller.h" #include "info/statistics/info_statistics_inner_widget.h" // FillLoading. diff --git a/Telegram/SourceFiles/info/bot/earn/info_earn_inner_widget.h b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_list.h similarity index 100% rename from Telegram/SourceFiles/info/bot/earn/info_earn_inner_widget.h rename to Telegram/SourceFiles/info/bot/earn/info_bot_earn_list.h diff --git a/Telegram/SourceFiles/info/bot/earn/info_earn_widget.cpp b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_widget.cpp similarity index 96% rename from Telegram/SourceFiles/info/bot/earn/info_earn_widget.cpp rename to Telegram/SourceFiles/info/bot/earn/info_bot_earn_widget.cpp index 59ddb37aa..03ad190ce 100644 --- a/Telegram/SourceFiles/info/bot/earn/info_earn_widget.cpp +++ b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_widget.cpp @@ -5,9 +5,9 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "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_memento.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/info/bot/earn/info_earn_widget.h b/Telegram/SourceFiles/info/bot/earn/info_bot_earn_widget.h similarity index 100% rename from Telegram/SourceFiles/info/bot/earn/info_earn_widget.h rename to Telegram/SourceFiles/info/bot/earn/info_bot_earn_widget.h diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp similarity index 99% rename from Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp rename to Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index 9fea4508c..84ad81390 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "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_earn.h" @@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/stickers/data_custom_emoji.h" #include "history/view/controls/history_view_webpage_processor.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/profile/info_profile_values.h" // Info::Profile::NameValue. #include "info/statistics/info_statistics_inner_widget.h" // FillLoading. diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.h b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.h similarity index 95% rename from Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.h rename to Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.h index d9f43192e..061d69b7e 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.h +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #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/wrap/vertical_layout.h" diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_widget.cpp similarity index 95% rename from Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.cpp rename to Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_widget.cpp index b0c38e1ad..dabd5e6ea 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_widget.cpp @@ -5,9 +5,9 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "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_memento.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_widget.h similarity index 100% rename from Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h rename to Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_widget.h diff --git a/Telegram/SourceFiles/iv/iv_controller.cpp b/Telegram/SourceFiles/iv/iv_controller.cpp index c717c8625..10e1e506b 100644 --- a/Telegram/SourceFiles/iv/iv_controller.cpp +++ b/Telegram/SourceFiles/iv/iv_controller.cpp @@ -346,9 +346,11 @@ void Controller::createWindow() { _window = std::make_unique(); const auto window = _window.get(); - window->windowActiveValue( - ) | rpl::filter([=](bool active) { - return _webview && active; + base::qt_signal_producer( + window->window()->windowHandle(), + &QWindow::activeChanged + ) | rpl::filter([=] { + return _webview && window->window()->windowHandle()->isActive(); }) | rpl::start_with_next([=] { setInnerFocus(); }, window->lifetime()); diff --git a/Telegram/SourceFiles/iv/iv_data.cpp b/Telegram/SourceFiles/iv/iv_data.cpp index 5258e6c9f..16f9c0d51 100644 --- a/Telegram/SourceFiles/iv/iv_data.cpp +++ b/Telegram/SourceFiles/iv/iv_data.cpp @@ -71,6 +71,12 @@ bool Data::partial() const { Data::~Data() = default; +void Data::updateCachedViews(int cachedViews) { + _source->updatedCachedViews = std::max( + _source->updatedCachedViews, + cachedViews); +} + void Data::prepare(const Options &options, Fn done) const { crl::async([source = *_source, options, done = std::move(done)] { done(Prepare(source, options)); diff --git a/Telegram/SourceFiles/iv/iv_data.h b/Telegram/SourceFiles/iv/iv_data.h index 87900bce3..cdb2d8708 100644 --- a/Telegram/SourceFiles/iv/iv_data.h +++ b/Telegram/SourceFiles/iv/iv_data.h @@ -45,6 +45,8 @@ public: [[nodiscard]] QString id() const; [[nodiscard]] bool partial() const; + void updateCachedViews(int cachedViews); + void prepare(const Options &options, Fn done) const; private: diff --git a/Telegram/SourceFiles/iv/iv_instance.cpp b/Telegram/SourceFiles/iv/iv_instance.cpp index 69df5f772..d070c93d2 100644 --- a/Telegram/SourceFiles/iv/iv_instance.cpp +++ b/Telegram/SourceFiles/iv/iv_instance.cpp @@ -57,6 +57,7 @@ constexpr auto kGeoPointScale = 1; constexpr auto kGeoPointZoomMin = 13; constexpr auto kMaxLoadParts = 5; constexpr auto kKeepLoadingParts = 8; +constexpr auto kAllowPageReloadAfter = 3 * crl::time(1000); } // namespace @@ -815,19 +816,19 @@ void Instance::show( } break; case Type::OpenPage: - case Type::OpenLink: + case Type::OpenLink: { if (!urlChecked) { break; } - _fullRequested[_shownSession].emplace(event.url); - _shownSession->api().request(MTPmessages_GetWebPage( - MTP_string(event.url), - MTP_int(0) + const auto session = _shownSession; + const auto url = event.url; + auto &requested = _fullRequested[session][url]; + requested.lastRequestedAt = crl::now(); + session->api().request(MTPmessages_GetWebPage( + MTP_string(url), + MTP_int(requested.hash) )).done([=](const MTPmessages_WebPage &result) { - _shownSession->data().processUsers(result.data().vusers()); - _shownSession->data().processChats(result.data().vchats()); - const auto page = _shownSession->data().processWebpage( - result.data().vwebpage()); + const auto page = processReceivedPage(session, url, result); if (page && page->iv) { const auto parts = event.url.split('#'); const auto hash = (parts.size() > 1) ? parts[1] : u""_q; @@ -838,7 +839,7 @@ void Instance::show( }).fail([=] { UrlClickHandler::Open(event.url); }).send(); - break; + } break; case Type::Report: if (const auto controller = _shownSession->tryResolveWindow()) { controller->window().activate(); @@ -954,15 +955,13 @@ void Instance::openWithIvPreferred( }; _ivRequestSession = session; _ivRequestUri = uri; - _fullRequested[session].emplace(url); + auto &requested = _fullRequested[session][url]; + requested.lastRequestedAt = crl::now(); _ivRequestId = session->api().request(MTPmessages_GetWebPage( MTP_string(url), - MTP_int(0) + MTP_int(requested.hash) )).done([=](const MTPmessages_WebPage &result) { - const auto &data = result.data(); - session->data().processUsers(data.vusers()); - session->data().processChats(data.vchats()); - finish(session->data().processWebpage(data.vwebpage())); + finish(processReceivedPage(session, url, result)); }).fail([=] { finish(nullptr); }).send(); @@ -971,24 +970,53 @@ void Instance::openWithIvPreferred( void Instance::requestFull( not_null session, const QString &id) { - if (!_tracking.contains(session) - || !_fullRequested[session].emplace(id).second) { + if (!_tracking.contains(session)) { 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( MTP_string(id), - MTP_int(0) + MTP_int(requested.hash) )).done([=](const MTPmessages_WebPage &result) { - session->data().processUsers(result.data().vusers()); - session->data().processChats(result.data().vchats()); - const auto page = session->data().processWebpage( - result.data().vwebpage()); + const auto page = processReceivedPage(session, id, result); if (page && page->iv && _shown && _shownSession == session) { _shown->update(page->iv.get()); } }).send(); } +WebPageData *Instance::processReceivedPage( + not_null 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) { if (!_shownSession) { return; diff --git a/Telegram/SourceFiles/iv/iv_instance.h b/Telegram/SourceFiles/iv/iv_instance.h index 1299bbddd..9083734ad 100644 --- a/Telegram/SourceFiles/iv/iv_instance.h +++ b/Telegram/SourceFiles/iv/iv_instance.h @@ -61,12 +61,23 @@ public: [[nodiscard]] rpl::lifetime &lifetime(); private: + struct FullResult { + crl::time lastRequestedAt = 0; + WebPageData *page = nullptr; + int32 hash = 0; + }; + void processOpenChannel(const QString &context); void processJoinChannel(const QString &context); void requestFull(not_null session, const QString &id); void trackSession(not_null session); + WebPageData *processReceivedPage( + not_null session, + const QString &url, + const MTPmessages_WebPage &result); + const not_null _delegate; std::unique_ptr _shown; @@ -77,7 +88,7 @@ private: base::flat_set>> _joining; base::flat_map< not_null, - base::flat_set> _fullRequested; + base::flat_map> _fullRequested; base::flat_map< not_null, diff --git a/Telegram/SourceFiles/iv/iv_prepare.cpp b/Telegram/SourceFiles/iv/iv_prepare.cpp index d5f537524..15d5edaa7 100644 --- a/Telegram/SourceFiles/iv/iv_prepare.cpp +++ b/Telegram/SourceFiles/iv/iv_prepare.cpp @@ -229,7 +229,9 @@ Parser::Parser(const Source &source, const Options &options) _result.name = source.name; _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()); _result.content = wrap(content, views); } diff --git a/Telegram/SourceFiles/iv/iv_prepare.h b/Telegram/SourceFiles/iv/iv_prepare.h index a896c79e0..ef919db2f 100644 --- a/Telegram/SourceFiles/iv/iv_prepare.h +++ b/Telegram/SourceFiles/iv/iv_prepare.h @@ -18,6 +18,7 @@ struct Source { std::optional webpagePhoto; std::optional webpageDocument; QString name; + int updatedCachedViews = 0; }; [[nodiscard]] Prepared Prepare(const Source &source, const Options &options); diff --git a/Telegram/SourceFiles/main/main_domain.cpp b/Telegram/SourceFiles/main/main_domain.cpp index 9b4b12067..714f7e291 100644 --- a/Telegram/SourceFiles/main/main_domain.cpp +++ b/Telegram/SourceFiles/main/main_domain.cpp @@ -403,6 +403,8 @@ bool Domain::removePasscodeIfEmpty() { return false; } _local->setPasscode(QByteArray()); + Core::App().settings().setSystemUnlockEnabled(false); + Core::App().saveSettingsDelayed(); return true; } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index fe56772d0..bfcda6f69 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1193,9 +1193,11 @@ void MainWidget::setInnerFocus() { _mainSection->setInnerFocus(); } else if (!_hider && _thirdSection) { _thirdSection->setInnerFocus(); - } else { - Assert(_dialogs != nullptr); + } else if (_dialogs) { _dialogs->setInnerFocus(); + } else { + // Maybe we're just closing a child window, content is destroyed. + _history->setFocus(); } } else if (_mainSection) { _mainSection->setInnerFocus(); @@ -1294,8 +1296,9 @@ void MainWidget::showHistory( } const auto unavailable = peer->computeUnavailableReason(); if (!unavailable.isEmpty()) { - Assert(isPrimary()); // windows todo - if (params.activation != anim::activation::background) { + if (!isPrimary()) { + _controller->window().close(); + } else if (params.activation != anim::activation::background) { _controller->show(Ui::MakeInformBox(unavailable)); _controller->window().activate(); } @@ -1951,10 +1954,9 @@ void MainWidget::showNonPremiumLimitToast(bool download) { }); } -void MainWidget::showBackFromStack( - const SectionShow ¶ms) { +bool MainWidget::showBackFromStack(const SectionShow ¶ms) { if (preventsCloseSection([=] { showBackFromStack(params); }, params)) { - return; + return false; } if (_stack.empty()) { @@ -1964,7 +1966,7 @@ void MainWidget::showBackFromStack( crl::on_main(this, [=] { _controller->widget()->setInnerFocus(); }); - return; + return (_dialogs != nullptr); } auto item = std::move(_stack.back()); _stack.pop_back(); @@ -1996,6 +1998,7 @@ void MainWidget::showBackFromStack( anim::activation::background)); } + return true; } void MainWidget::orderWidgets() { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 07b960fdd..6c30d38b1 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -152,8 +152,7 @@ public: const SectionShow ¶ms); void updateColumnLayout(); bool stackIsEmpty() const; - void showBackFromStack( - const SectionShow ¶ms); + bool showBackFromStack(const SectionShow ¶ms); void orderWidgets(); QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms); void checkMainSectionToLayer(); diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 41c75c3e4..8895cde1f 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -510,15 +510,15 @@ OverlayWidget::OverlayWidget() return base::EventFilterResult::Cancel; } } else if (e->type() == QEvent::WindowStateChange) { - const auto state = _window->windowState(); - if (state & Qt::WindowMinimized || Platform::IsMac()) { - } else if (state & Qt::WindowMaximized) { + const auto state = window()->windowState(); + if (state == Qt::WindowMinimized || Platform::IsMac()) { + } else if (state == Qt::WindowMaximized) { if (_fullscreen || _windowed) { _fullscreen = _windowed = false; savePosition(); } } else if (_fullscreen || _windowed) { - } else if (state & Qt::WindowFullScreen) { + } else if (state == Qt::WindowFullScreen) { _fullscreen = true; savePosition(); } else { @@ -3856,16 +3856,12 @@ void OverlayWidget::updatePowerSaveBlocker( && !IsPausedOrPausing(state.state) && !IsStoppedOrStopping(state.state); - _window->shownValue() | rpl::filter([=](bool shown) { - return shown; - }) | rpl::take(1) | rpl::start_with_next([=] { - base::UpdatePowerSaveBlocker( - _streamed->powerSaveBlocker, - block, - base::PowerSaveBlockType::PreventDisplaySleep, - [] { return u"Video playback is active"_q; }, - [=] { return window(); }); - }, lifetime()); + base::UpdatePowerSaveBlocker( + _streamed->powerSaveBlocker, + block, + base::PowerSaveBlockType::PreventDisplaySleep, + [] { return u"Video playback is active"_q; }, + [=] { return _window->windowHandle(); }); } QImage OverlayWidget::transformedShownContent() const { diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp index 93865a587..4ab0ce839 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp @@ -65,7 +65,7 @@ QByteArray DnsUserAgent() { static const auto kResult = QByteArray( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/124.0.0.0 Safari/537.36"); + "Chrome/126.0.0.0 Safari/537.36"); return kResult; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 07ad565a5..25ac88992 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/linux/specific_linux.h" +#include "base/openssl_help.h" #include "base/random.h" #include "base/platform/base_platform_info.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(binary.data()), + binary.size()).toBase64(QByteArray::Base64UrlEncoding); + return base64.mid(0, kHashForSocketPathLength); +} + } // namespace namespace Platform { @@ -686,8 +697,8 @@ void start() { Webview::WebKitGTK::SetSocketPath(u"%1/%2-%3-webview-%4"_q.arg( QDir::tempPath(), - h, - QCoreApplication::applicationName(), + HashForSocketPath(d), + u"TD"_q,//QCoreApplication::applicationName(), - make path smaller. u"%1"_q).toStdString()); InstallLauncher(); diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 3e720ba59..648a64900 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -280,10 +280,7 @@ void FillCreditOptions( inner->paintRequest( ) | rpl::start_with_next([=](const QRect &rect) { auto p = QPainter(inner); - p.drawImage( - 0, - (buttonHeight - stars.height()) / 2, - stars); + p.drawImage(0, 0, stars); const auto textLeft = diffBetweenTextAndStar + stars.width() / style::DevicePixelRatio(); p.setPen(st.textFg); diff --git a/Telegram/SourceFiles/settings/settings_experimental.cpp b/Telegram/SourceFiles/settings/settings_experimental.cpp index 93e9e74dc..f578bce82 100644 --- a/Telegram/SourceFiles/settings/settings_experimental.cpp +++ b/Telegram/SourceFiles/settings/settings_experimental.cpp @@ -152,6 +152,7 @@ void SetupExperimental( addToggle(kOptionAutoScrollInactiveChat); addToggle(Window::Notifications::kOptionGNotification); addToggle(Core::kOptionFreeType); + addToggle(Core::kOptionSkipUrlSchemeRegister); addToggle(Data::kOptionExternalVideoPlayer); addToggle(Window::kOptionNewWindowsSizeAsFirst); } diff --git a/Telegram/SourceFiles/settings/settings_local_passcode.cpp b/Telegram/SourceFiles/settings/settings_local_passcode.cpp index db21f717b..193445caf 100644 --- a/Telegram/SourceFiles/settings/settings_local_passcode.cpp +++ b/Telegram/SourceFiles/settings/settings_local_passcode.cpp @@ -80,6 +80,7 @@ private: rpl::event_stream<> _setInnerFocus; rpl::event_stream _showOther; rpl::event_stream<> _showBack; + bool _systemUnlockWithBiometric = false; }; @@ -97,6 +98,13 @@ rpl::producer LocalPasscodeEnter::title() { void LocalPasscodeEnter::setupContent() { const auto content = Ui::CreateChild(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 isCheck = (enterType() == EnterType::Check); [[maybe_unused]] const auto isChange = (enterType() == EnterType::Change); @@ -242,8 +250,10 @@ void LocalPasscodeEnter::setupContent() { } SetPasscode(_controller, newText); if (isCreate) { - Core::App().settings().setSystemUnlockEnabled(true); - Core::App().saveSettingsDelayed(); + if (Platform::IsWindows() || _systemUnlockWithBiometric) { + Core::App().settings().setSystemUnlockEnabled(true); + Core::App().saveSettingsDelayed(); + } _showOther.fire(LocalPasscodeManageId()); } else if (isChange) { _showBack.fire({}); @@ -518,38 +528,77 @@ void LocalPasscodeManage::setupContent() { )->setDuration(0); const auto systemUnlockContent = systemUnlockWrap->entity(); - Ui::AddSkip(systemUnlockContent); + enum class UnlockType { + None, + Default, + Biometrics, + Companion, + }; + const auto unlockType = systemUnlockContent->lifetime().make_state< + rpl::variable + >(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()); - Ui::AddSkip(systemUnlockContent); - - 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)); + systemUnlockWrap->toggleOn(unlockType->value( + ) | rpl::map(rpl::mappers::_1 != UnlockType::None)); Ui::ResizeFitChild(this, content); } @@ -562,6 +611,8 @@ QPointer LocalPasscodeManage::createPinnedToBottom( .text = tr::lng_settings_passcode_disable_sure(), .confirmed = [=](Fn &&close) { SetPasscode(_controller, QString()); + Core::App().settings().setSystemUnlockEnabled(false); + Core::App().saveSettingsDelayed(); close(); _showBack.fire({}); diff --git a/Telegram/SourceFiles/ui/menu_icons.style b/Telegram/SourceFiles/ui/menu_icons.style index ce1670203..96838e8a5 100644 --- a/Telegram/SourceFiles/ui/menu_icons.style +++ b/Telegram/SourceFiles/ui/menu_icons.style @@ -157,6 +157,8 @@ menuIconFont: icon {{ "menu/fonts", menuIconColor }}; menuIconFactcheck: icon {{ "menu/factcheck", menuIconColor }}; menuIconWinHello: icon {{ "menu/passcode_winhello", menuIconColor }}; menuIconTouchID: icon {{ "menu/passcode_finger", menuIconColor }}; +menuIconAppleWatch: icon {{ "menu/passcode_watch", menuIconColor }}; +menuIconSystemPwd: menuIconPermissions; menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }}; menuIconTTLAnyTextPosition: point(11px, 22px); diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index e6453fbf2..02350886e 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -110,8 +110,17 @@ PasscodeLockWidget::PasscodeLockWidget( using namespace rpl::mappers; if (Core::App().settings().systemUnlockEnabled()) { - _systemUnlockAvailable = base::SystemUnlockStatus() - | rpl::map(_1 == base::SystemUnlockAvailability::Available); + _systemUnlockAvailable = base::SystemUnlockStatus( + 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()) { _systemUnlockAllowed = _systemUnlockAvailable.value(); setupSystemUnlock(); @@ -122,11 +131,22 @@ PasscodeLockWidget::PasscodeLockWidget( } 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( this, - (Platform::IsWindows() - ? tr::lng_passcode_winhello() - : tr::lng_passcode_touchid()), + std::move(text), st::passcodeSystemUnlockLater); _logout->geometryValue( ) | rpl::start_with_next([=](QRect logout) { @@ -137,7 +157,8 @@ void PasscodeLockWidget::setupSystemUnlockInfo() { st::boxRowPadding.left(), logout.y() + logout.height() + st::passcodeSystemUnlockSkip); }, info->lifetime()); - info->showOn(_systemUnlockAvailable.value()); + info->showOn(_systemUnlockAvailable.value( + ) | rpl::map(rpl::mappers::_1 != SystemUnlockType::None)); } void PasscodeLockWidget::setupSystemUnlock() { @@ -152,10 +173,21 @@ void PasscodeLockWidget::setupSystemUnlock() { const auto button = Ui::CreateChild( _passcode.data(), - (Platform::IsWindows() - ? st::passcodeSystemWinHello - : st::passcodeSystemTouchID)); - button->showOn(_systemUnlockAllowed.value()); + st::passcodeSystemUnlock); + if (!Platform::IsWindows()) { + using namespace base; + _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) { button->moveToRight(0, size.height() - button->height()); }, button->lifetime()); @@ -177,7 +209,7 @@ void PasscodeLockWidget::suggestSystemUnlock() { using namespace base; _systemUnlockAllowed.value( ) | rpl::filter( - rpl::mappers::_1 + rpl::mappers::_1 != SystemUnlockType::None ) | rpl::take(1) | rpl::start_with_next([=] { const auto weak = Ui::MakeWeak(this); const auto done = [weak](SystemUnlockResult result) { diff --git a/Telegram/SourceFiles/window/window_lock_widgets.h b/Telegram/SourceFiles/window/window_lock_widgets.h index 8c48850fb..03c6b59b3 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.h +++ b/Telegram/SourceFiles/window/window_lock_widgets.h @@ -65,6 +65,13 @@ protected: void resizeEvent(QResizeEvent *e) override; private: + enum class SystemUnlockType : uchar { + None, + Default, + Biometrics, + Companion, + }; + void paintContent(QPainter &p) override; void setupSystemUnlockInfo(); @@ -75,8 +82,8 @@ private: void submit(); void error(); - rpl::variable _systemUnlockAvailable = false; - rpl::variable _systemUnlockAllowed = false; + rpl::variable _systemUnlockAvailable; + rpl::variable _systemUnlockAllowed; object_ptr _passcode; object_ptr _submit; object_ptr _logout; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index e4b892a3e..9398d33a1 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -67,7 +67,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_controller.h" #include "info/info_memento.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/statistics/info_statistics_widget.h" #include "info/stories/info_stories_widget.h" @@ -694,8 +694,9 @@ void Filler::addNewWindow() { _addAction(tr::lng_context_new_window(tr::now), [=] { Ui::PreventDelayedActivation(); if (const auto strong = weak.get()) { + const auto forum = !strong->asTopic() && peer->isForum(); controller->showInNewWindow(SeparateId( - peer->isForum() ? SeparateType::Forum : SeparateType::Chat, + forum ? SeparateType::Forum : SeparateType::Chat, strong)); } }, &st::menuIconNewWindow); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 7ab87cd80..34c7f9c0b 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "window/window_filters_menu.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_controller.h" #include "inline_bots/bot_attach_web_view.h" @@ -1668,8 +1668,9 @@ void SessionController::showForum( ) | rpl::start_with_next([=, history = forum->history()] { const auto now = activeChatCurrent().owningHistory(); const auto showHistory = !now || (now == history); + const auto weak = base::make_weak(this); closeForum(); - if (showHistory) { + if (weak && showHistory) { showPeerHistory(history, { SectionShow::Way::Backward, anim::type::normal, @@ -1684,7 +1685,7 @@ void SessionController::closeForum() { if (const auto forum = _shownForum.current()) { const auto id = windowId(); if (id.type == SeparateType::Forum) { - const auto initial = id.thread->asForum(); + const auto initial = id.forum(); if (!initial || initial == forum) { Core::App().closeWindow(_window); } else { @@ -2537,7 +2538,13 @@ void SessionController::showBackFromStack(const SectionShow ¶ms) { return topic && topic->forum()->topicDeleted(topic->rootId()); }; 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()); } diff --git a/Telegram/build/version b/Telegram/build/version index fdada4a89..553191613 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 5002000 +AppVersion 5002002 AppVersionStrMajor 5.2 -AppVersionStrSmall 5.2 -AppVersionStr 5.2.0 +AppVersionStrSmall 5.2.2 +AppVersionStr 5.2.2 BetaChannel 0 AlphaVersion 0 -AppVersionOriginal 5.2 +AppVersionOriginal 5.2.2 diff --git a/Telegram/lib_base b/Telegram/lib_base index b512eead3..f30400147 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit b512eead302cb7b509869778348d60fef64bc19b +Subproject commit f30400147d997fedc787e214467d305db6c159e7 diff --git a/Telegram/lib_spellcheck b/Telegram/lib_spellcheck index 59d922617..0b7622ff3 160000 --- a/Telegram/lib_spellcheck +++ b/Telegram/lib_spellcheck @@ -1 +1 @@ -Subproject commit 59d92261783ae403e8708f972c36be3d21ab064d +Subproject commit 0b7622ff38778e9cd03d3997de59351973480a1f diff --git a/changelog.txt b/changelog.txt index ad1f99ab1..6e398bcc6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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) - Pay for content with Telegram Stars.