From 94b489835c24a387a31c71be01d5e9a652304c6b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 3 Feb 2023 17:51:26 +0400 Subject: [PATCH] Add chat name / account name / unread count title settings. --- Telegram/Resources/langs/lang.strings | 4 + Telegram/SourceFiles/core/application.cpp | 12 ++ Telegram/SourceFiles/core/application.h | 1 + Telegram/SourceFiles/core/core_settings.cpp | 22 ++- Telegram/SourceFiles/core/core_settings.h | 20 +++ Telegram/SourceFiles/main/main_domain.cpp | 10 ++ Telegram/SourceFiles/main/main_domain.h | 1 + .../settings/settings_advanced.cpp | 138 +++++++++++++++--- .../SourceFiles/settings/settings_advanced.h | 3 + .../SourceFiles/settings/settings_intro.cpp | 3 + Telegram/SourceFiles/window/main_window.cpp | 32 +++- .../window/window_session_controller.cpp | 15 +- .../window/window_session_controller.h | 6 + 13 files changed, 233 insertions(+), 34 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 865e14498d5ec6..f942fccb1922a2 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -486,6 +486,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_workmode_tray" = "Show tray icon"; "lng_settings_workmode_window" = "Show taskbar icon"; "lng_settings_close_to_taskbar" = "Close to taskbar"; +"lng_settings_window_system" = "Window title"; +"lng_settings_title_chat_name" = "Show chat name"; +"lng_settings_title_account_name" = "Show active account"; +"lng_settings_title_total_count" = "Total unread count"; "lng_settings_native_frame" = "Use system window frame"; "lng_settings_auto_start" = "Launch Telegram when system starts"; "lng_settings_start_min" = "Launch minimized"; diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index d19dd419e5b9b9..f771af00f2bd90 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -170,6 +170,12 @@ Application::Application(not_null launcher) passcodeLockChanges( ) | rpl::start_with_next([=] { _notifications->updateAll(); + updateWindowTitles(); + }, _lifetime); + + settings().windowTitleContentChanges( + ) | rpl::start_with_next([=] { + updateWindowTitles(); }, _lifetime); _domain->activeSessionChanges( @@ -1067,6 +1073,12 @@ void Application::preventOrInvoke(Fn &&callback) { _lastActivePrimaryWindow->preventOrInvoke(std::move(callback)); } +void Application::updateWindowTitles() { + enumerateWindows([](not_null window) { + window->widget()->updateTitle(); + }); +} + void Application::lockByPasscode() { enumerateWindows([&](not_null w) { _passcodeLock = true; diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index d4ed245a4fc7ba..462e4370b8b07b 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -335,6 +335,7 @@ class Application final : public QObject { void startSystemDarkModeViewer(); void startTray(); + void updateWindowTitles(); void setLastActiveWindow(Window::Controller *window); void showAccount(not_null account); void enumerateWindows( diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 6790af9b2aab85..8d3671b696ff65 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -159,7 +159,8 @@ QByteArray Settings::serialize() const { + sizeof(qint32) * 7 + (skipLanguages.size() * sizeof(quint64)) + sizeof(qint32) - + sizeof(quint64); + + sizeof(quint64) + + sizeof(qint32) * 3; auto result = QByteArray(); result.reserve(size); @@ -287,7 +288,10 @@ QByteArray Settings::serialize() const { stream << qint32(_translateChatEnabled.current() ? 1 : 0) - << quint64(QLocale::Language(_translateToRaw.current())); + << quint64(QLocale::Language(_translateToRaw.current())) + << qint32(_windowTitleContent.current().hideChatName ? 1 : 0) + << qint32(_windowTitleContent.current().hideAccountName ? 1 : 0) + << qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0); } return result; } @@ -387,6 +391,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 rememberedDeleteMessageOnlyForYou = _rememberedDeleteMessageOnlyForYou ? 1 : 0; qint32 translateChatEnabled = _translateChatEnabled.current() ? 1 : 0; quint64 translateToRaw = _translateToRaw.current(); + qint32 hideChatName = _windowTitleContent.current().hideChatName ? 1 : 0; + qint32 hideAccountName = _windowTitleContent.current().hideAccountName ? 1 : 0; + qint32 hideTotalUnread = _windowTitleContent.current().hideTotalUnread ? 1 : 0; stream >> themesAccentColors; if (!stream.atEnd()) { @@ -606,6 +613,12 @@ void Settings::addFromSerialized(const QByteArray &serialized) { >> translateChatEnabled >> translateToRaw; } + if (!stream.atEnd()) { + stream + >> hideChatName + >> hideAccountName + >> hideTotalUnread; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -791,6 +804,11 @@ void Settings::addFromSerialized(const QByteArray &serialized) { _rememberedDeleteMessageOnlyForYou = (rememberedDeleteMessageOnlyForYou == 1); _translateChatEnabled = (translateChatEnabled == 1); _translateToRaw = int(QLocale::Language(translateToRaw)); + _windowTitleContent = WindowTitleContent{ + .hideChatName = (hideChatName == 1), + .hideAccountName = (hideAccountName == 1), + .hideTotalUnread = (hideTotalUnread == 1), + }; } QString Settings::getSoundPath(const QString &key) const { diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index d653f2f37aa9a6..95490bbb15d373 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -54,6 +54,16 @@ struct WindowPosition { int h = 0; }; +struct WindowTitleContent { + bool hideChatName : 1 = false; + bool hideAccountName : 1 = false; + bool hideTotalUnread : 1 = false; + + friend inline constexpr auto operator<=>( + WindowTitleContent, + WindowTitleContent) = default; +}; + constexpr auto kRecentEmojiLimit = 42; struct RecentEmojiDocument { @@ -598,6 +608,15 @@ class Settings final { [[nodiscard]] rpl::producer systemDarkModeEnabledChanges() const { return _systemDarkModeEnabled.changes(); } + [[nodiscard]] WindowTitleContent windowTitleContent() const { + return _windowTitleContent.current(); + } + [[nodiscard]] rpl::producer windowTitleContentChanges() const { + return _windowTitleContent.changes(); + } + void setWindowTitleContent(WindowTitleContent content) { + _windowTitleContent = content; + } [[nodiscard]] const WindowPosition &windowPosition() const { return _windowPosition; } @@ -837,6 +856,7 @@ class Settings final { rpl::variable _nativeWindowFrame = false; rpl::variable> _systemDarkMode = std::nullopt; rpl::variable _systemDarkModeEnabled = false; + rpl::variable _windowTitleContent; WindowPosition _windowPosition; // per-window bool _disableOpenGL = false; rpl::variable _workMode = WorkMode::WindowAndTray; diff --git a/Telegram/SourceFiles/main/main_domain.cpp b/Telegram/SourceFiles/main/main_domain.cpp index 9e237dfe999bd7..396aaeb6d46b86 100644 --- a/Telegram/SourceFiles/main/main_domain.cpp +++ b/Telegram/SourceFiles/main/main_domain.cpp @@ -181,6 +181,16 @@ Account *Domain::maybeLastOrSomeAuthedAccount() { return result; } +int Domain::accountsAuthedCount() const { + auto result = 0; + for (const auto &[index, account] : _accounts) { + if (account->sessionExists()) { + ++result; + } + } + return result; +} + rpl::producer Domain::activeValue() const { return _active.value(); } diff --git a/Telegram/SourceFiles/main/main_domain.h b/Telegram/SourceFiles/main/main_domain.h index f1f93b624d5da4..1a39e8e7fcbe2f 100644 --- a/Telegram/SourceFiles/main/main_domain.h +++ b/Telegram/SourceFiles/main/main_domain.h @@ -54,6 +54,7 @@ class Domain final { [[nodiscard]] rpl::producer activeValue() const; [[nodiscard]] rpl::producer<> accountsChanges() const; [[nodiscard]] Account *maybeLastOrSomeAuthedAccount(); + [[nodiscard]] int accountsAuthedCount() const; // Expects(started()); [[nodiscard]] Account &active() const; diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 265333a776b37c..7f3ed4469ff2d5 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -345,6 +345,85 @@ void SetupSpellchecker( #endif // !TDESKTOP_DISABLE_SPELLCHECK } +void SetupWindowTitleContent( + Window::SessionController *controller, + not_null container) { + const auto checkbox = [&](rpl::producer &&label, bool checked) { + return object_ptr( + container, + std::move(label), + checked, + st::settingsCheckbox); + }; + const auto addCheckbox = [&]( + rpl::producer &&label, + bool checked) { + return container->add( + checkbox(std::move(label), checked), + st::settingsCheckboxPadding); + }; + const auto settings = &Core::App().settings(); + if (controller) { + const auto content = [=] { + return settings->windowTitleContent(); + }; + const auto showChatName = addCheckbox( + tr::lng_settings_title_chat_name(), + !content().hideChatName); + showChatName->checkedChanges( + ) | rpl::filter([=](bool checked) { + return (checked == content().hideChatName); + }) | rpl::start_with_next([=](bool checked) { + auto updated = content(); + updated.hideChatName = !checked; + settings->setWindowTitleContent(updated); + Core::App().saveSettingsDelayed(); + }, showChatName->lifetime()); + + if (Core::App().domain().accountsAuthedCount() > 1) { + const auto showAccountName = addCheckbox( + tr::lng_settings_title_account_name(), + !content().hideAccountName); + showAccountName->checkedChanges( + ) | rpl::filter([=](bool checked) { + return (checked == content().hideAccountName); + }) | rpl::start_with_next([=](bool checked) { + auto updated = content(); + updated.hideAccountName = !checked; + settings->setWindowTitleContent(updated); + Core::App().saveSettingsDelayed(); + }, showAccountName->lifetime()); + } + + const auto showTotalUnread = addCheckbox( + tr::lng_settings_title_total_count(), + !content().hideTotalUnread); + showTotalUnread->checkedChanges( + ) | rpl::filter([=](bool checked) { + return (checked == content().hideTotalUnread); + }) | rpl::start_with_next([=](bool checked) { + auto updated = content(); + updated.hideTotalUnread = !checked; + settings->setWindowTitleContent(updated); + Core::App().saveSettingsDelayed(); + }, showTotalUnread->lifetime()); + } + + if (Ui::Platform::NativeWindowFrameSupported()) { + const auto nativeFrame = addCheckbox( + tr::lng_settings_native_frame(), + Core::App().settings().nativeWindowFrame()); + + nativeFrame->checkedChanges( + ) | rpl::filter([](bool checked) { + return (checked != Core::App().settings().nativeWindowFrame()); + }) | rpl::start_with_next([=](bool checked) { + Core::App().settings().setNativeWindowFrame(checked); + Core::App().saveSettingsDelayed(); + }, nativeFrame->lifetime()); + } +} + void SetupSystemIntegrationContent( Window::SessionController *controller, not_null container) { @@ -469,20 +548,6 @@ void SetupSystemIntegrationContent( }, closeToTaskbar->lifetime()); #endif // Q_OS_MAC - if (Ui::Platform::NativeWindowFrameSupported()) { - const auto nativeFrame = addCheckbox( - tr::lng_settings_native_frame(), - Core::App().settings().nativeWindowFrame()); - - nativeFrame->checkedChanges( - ) | rpl::filter([](bool checked) { - return (checked != Core::App().settings().nativeWindowFrame()); - }) | rpl::start_with_next([=](bool checked) { - Core::App().settings().setNativeWindowFrame(checked); - Core::App().saveSettingsDelayed(); - }, nativeFrame->lifetime()); - } - if (Platform::AutostartSupported() && controller) { const auto minimizedToggled = [=] { return cStartMinimized() @@ -560,20 +625,39 @@ void SetupSystemIntegrationContent( } } -void SetupSystemIntegrationOptions( +template +void CheckNonEmptyOptions( not_null controller, - not_null container) { + not_null container, + Fill fill) { auto wrap = object_ptr(container); - SetupSystemIntegrationContent(controller, wrap.data()); + fill(controller, wrap.data()); if (wrap->count() > 0) { container->add(object_ptr( container, std::move(wrap))); - AddSkip(container, st::settingsCheckboxesSkip); } } +void SetupSystemIntegrationOptions( + not_null controller, + not_null container) { + CheckNonEmptyOptions( + controller, + container, + SetupSystemIntegrationContent); +} + +void SetupWindowTitleOptions( + not_null controller, + not_null container) { + CheckNonEmptyOptions( + controller, + container, + SetupWindowTitleContent); +} + void SetupAnimations(not_null container) { AddButton( container, @@ -731,10 +815,19 @@ void SetupPerformance( #endif // Q_OS_WIN } +void SetupWindowTitle( + not_null controller, + not_null container) { + AddDivider(container); + AddSkip(container); + AddSubsectionTitle(container, tr::lng_settings_window_system()); + SetupWindowTitleOptions(controller, container); + AddSkip(container); +} + void SetupSystemIntegration( not_null controller, - not_null container, - Fn showOther) { + not_null container) { AddDivider(container); AddSkip(container); AddSubsectionTitle(container, tr::lng_settings_system_integration()); @@ -785,9 +878,8 @@ void Advanced::setupContent(not_null controller) { addDivider(); SetupDataStorage(controller, content); SetupAutoDownload(controller, content); - SetupSystemIntegration(controller, content, [=](Type type) { - _showOther.fire_copy(type); - }); + SetupWindowTitle(controller, content); + SetupSystemIntegration(controller, content); empty = false; AddDivider(content); diff --git a/Telegram/SourceFiles/settings/settings_advanced.h b/Telegram/SourceFiles/settings/settings_advanced.h index ff7685f963a3c7..940c362a62bda6 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.h +++ b/Telegram/SourceFiles/settings/settings_advanced.h @@ -27,6 +27,9 @@ bool HasUpdate(); void SetupUpdate( not_null container, Fn showOther); +void SetupWindowTitleContent( + Window::SessionController *controller, + not_null container); void SetupSystemIntegrationContent( Window::SessionController *controller, not_null container); diff --git a/Telegram/SourceFiles/settings/settings_intro.cpp b/Telegram/SourceFiles/settings/settings_intro.cpp index 1facf1e3aeab10..68150ef1d31f29 100644 --- a/Telegram/SourceFiles/settings/settings_intro.cpp +++ b/Telegram/SourceFiles/settings/settings_intro.cpp @@ -77,6 +77,9 @@ object_ptr CreateIntroSettings( SetupSystemIntegrationContent( window->sessionController(), wrap.data()); + SetupWindowTitleContent( + window->sessionController(), + wrap.data()); if (wrap->count() > 0) { AddDivider(result); AddSkip(result); diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 2e2e8c9fec6596..b98756dc3ea981 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -17,12 +17,14 @@ For license and copyright information please follow this link: #include "window/window_lock_widgets.h" #include "window/window_controller.h" #include "main/main_account.h" // Account::sessionValue. +#include "main/main_domain.h" #include "core/application.h" #include "core/sandbox.h" #include "core/shortcuts.h" #include "lang/lang_keys.h" #include "data/data_session.h" #include "data/data_forum_topic.h" +#include "data/data_user.h" #include "main/main_session.h" #include "main/main_session_settings.h" #include "base/options.h" @@ -837,15 +839,24 @@ void MainWindow::updateTitle() { return; } - const auto counter = Core::App().unreadBadge(); - const auto basic = (counter > 0) - ? u"Telegram (%1)"_q.arg(counter) - : u"Telegram"_q; - const auto session = _controller->sessionController(); - const auto key = session ? session->activeChatCurrent() : Dialogs::Key(); + const auto settings = Core::App().settings().windowTitleContent(); + const auto locked = Core::App().passcodeLocked(); + const auto counter = settings.hideTotalUnread + ? 0 + : Core::App().unreadBadge(); + const auto added = (counter > 0) ? u" (%1)"_q.arg(counter) : QString(); + const auto session = locked ? nullptr : _controller->sessionController(); + const auto user = (session + && !settings.hideAccountName + && Core::App().domain().accountsAuthedCount() > 1) + ? session->authedName() + : QString(); + const auto key = (session && !settings.hideChatName) + ? session->activeChatCurrent() + : Dialogs::Key(); const auto thread = key ? key.thread() : nullptr; if (!thread) { - setTitle(basic); + setTitle((user.isEmpty() ? u"Telegram"_q : user) + added); return; } const auto history = thread->owningHistory(); @@ -859,7 +870,12 @@ void MainWindow::updateTitle() { const auto primary = (threadCounter > 0) ? u"(%1) %2"_q.arg(threadCounter).arg(name) : name; - setTitle(primary + u" \u2013 "_q + basic); + const auto middle = !user.isEmpty() + ? (u" @ "_q + user) + : !added.isEmpty() + ? u" \u2013"_q + : QString(); + setTitle(primary + middle + added); } QRect MainWindow::computeDesktopRect() const { diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 90e0fd18051760..67b82fba99693c 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -745,10 +745,23 @@ SessionController::SessionController( } }, _lifetime); + _authedName = session->user()->name(); session->changes().peerUpdates( Data::PeerUpdate::Flag::FullInfo + | Data::PeerUpdate::Flag::Name ) | rpl::filter([=](const Data::PeerUpdate &update) { - return (update.peer == _showEditPeer); + if (update.flags & Data::PeerUpdate::Flag::Name) { + const auto user = session->user(); + if (update.peer == user) { + _authedName = user->name(); + const auto &settings = Core::App().settings(); + if (!settings.windowTitleContent().hideAccountName) { + widget()->updateTitle(); + } + } + } + return (update.flags & Data::PeerUpdate::Flag::FullInfo) + && (update.peer == _showEditPeer); }) | rpl::start_with_next([=] { show(Box(this, base::take(_showEditPeer))); }, lifetime()); diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 771f95aeb0454d..76f12014a60014 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -553,6 +553,10 @@ class SessionController : public SessionNavigation { return *_cachedReactionIconFactory; } + [[nodiscard]] QString authedName() const { + return _authedName; + } + void setPremiumRef(const QString &ref); [[nodiscard]] QString premiumRef() const; @@ -605,6 +609,8 @@ class SessionController : public SessionNavigation { const std::unique_ptr _emojiInteractions; const bool _isPrimary = false; + QString _authedName; + using SendingAnimation = Ui::MessageSendingAnimationController; const std::unique_ptr _sendingAnimation;