Add chat name / account name / unread count title settings.

This commit is contained in:
John Preston 2023-02-03 17:51:26 +04:00
parent eb64ffcd86
commit 94b489835c
13 changed files with 233 additions and 34 deletions

View file

@ -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";

View file

@ -170,6 +170,12 @@ Application::Application(not_null<Launcher*> 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<void()> &&callback) {
_lastActivePrimaryWindow->preventOrInvoke(std::move(callback));
}
void Application::updateWindowTitles() {
enumerateWindows([](not_null<Window::Controller*> window) {
window->widget()->updateTitle();
});
}
void Application::lockByPasscode() {
enumerateWindows([&](not_null<Window::Controller*> w) {
_passcodeLock = true;

View file

@ -335,6 +335,7 @@ private:
void startSystemDarkModeViewer();
void startTray();
void updateWindowTitles();
void setLastActiveWindow(Window::Controller *window);
void showAccount(not_null<Main::Account*> account);
void enumerateWindows(

View file

@ -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 {

View file

@ -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 @@ public:
[[nodiscard]] rpl::producer<bool> systemDarkModeEnabledChanges() const {
return _systemDarkModeEnabled.changes();
}
[[nodiscard]] WindowTitleContent windowTitleContent() const {
return _windowTitleContent.current();
}
[[nodiscard]] rpl::producer<WindowTitleContent> windowTitleContentChanges() const {
return _windowTitleContent.changes();
}
void setWindowTitleContent(WindowTitleContent content) {
_windowTitleContent = content;
}
[[nodiscard]] const WindowPosition &windowPosition() const {
return _windowPosition;
}
@ -837,6 +856,7 @@ private:
rpl::variable<bool> _nativeWindowFrame = false;
rpl::variable<std::optional<bool>> _systemDarkMode = std::nullopt;
rpl::variable<bool> _systemDarkModeEnabled = false;
rpl::variable<WindowTitleContent> _windowTitleContent;
WindowPosition _windowPosition; // per-window
bool _disableOpenGL = false;
rpl::variable<WorkMode> _workMode = WorkMode::WindowAndTray;

View file

@ -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<Account*> Domain::activeValue() const {
return _active.value();
}

View file

@ -54,6 +54,7 @@ public:
[[nodiscard]] rpl::producer<Account*> activeValue() const;
[[nodiscard]] rpl::producer<> accountsChanges() const;
[[nodiscard]] Account *maybeLastOrSomeAuthedAccount();
[[nodiscard]] int accountsAuthedCount() const;
// Expects(started());
[[nodiscard]] Account &active() const;

View file

@ -345,6 +345,85 @@ void SetupSpellchecker(
#endif // !TDESKTOP_DISABLE_SPELLCHECK
}
void SetupWindowTitleContent(
Window::SessionController *controller,
not_null<Ui::VerticalLayout*> container) {
const auto checkbox = [&](rpl::producer<QString> &&label, bool checked) {
return object_ptr<Ui::Checkbox>(
container,
std::move(label),
checked,
st::settingsCheckbox);
};
const auto addCheckbox = [&](
rpl::producer<QString> &&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<Ui::VerticalLayout*> 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 <typename Fill>
void CheckNonEmptyOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
not_null<Ui::VerticalLayout*> container,
Fill fill) {
auto wrap = object_ptr<Ui::VerticalLayout>(container);
SetupSystemIntegrationContent(controller, wrap.data());
fill(controller, wrap.data());
if (wrap->count() > 0) {
container->add(object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap)));
AddSkip(container, st::settingsCheckboxesSkip);
}
}
void SetupSystemIntegrationOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
CheckNonEmptyOptions(
controller,
container,
SetupSystemIntegrationContent);
}
void SetupWindowTitleOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
CheckNonEmptyOptions(
controller,
container,
SetupWindowTitleContent);
}
void SetupAnimations(not_null<Ui::VerticalLayout*> container) {
AddButton(
container,
@ -731,10 +815,19 @@ void SetupPerformance(
#endif // Q_OS_WIN
}
void SetupWindowTitle(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
AddSubsectionTitle(container, tr::lng_settings_window_system());
SetupWindowTitleOptions(controller, container);
AddSkip(container);
}
void SetupSystemIntegration(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container,
Fn<void(Type)> showOther) {
not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
AddSubsectionTitle(container, tr::lng_settings_system_integration());
@ -785,9 +878,8 @@ void Advanced::setupContent(not_null<Window::SessionController*> 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);

View file

@ -27,6 +27,9 @@ bool HasUpdate();
void SetupUpdate(
not_null<Ui::VerticalLayout*> container,
Fn<void(Type)> showOther);
void SetupWindowTitleContent(
Window::SessionController *controller,
not_null<Ui::VerticalLayout*> container);
void SetupSystemIntegrationContent(
Window::SessionController *controller,
not_null<Ui::VerticalLayout*> container);

View file

@ -77,6 +77,9 @@ object_ptr<Ui::RpWidget> CreateIntroSettings(
SetupSystemIntegrationContent(
window->sessionController(),
wrap.data());
SetupWindowTitleContent(
window->sessionController(),
wrap.data());
if (wrap->count() > 0) {
AddDivider(result);
AddSkip(result);

View file

@ -17,12 +17,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#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 {

View file

@ -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<EditPeerInfoBox>(this, base::take(_showEditPeer)));
}, lifetime());

View file

@ -553,6 +553,10 @@ public:
return *_cachedReactionIconFactory;
}
[[nodiscard]] QString authedName() const {
return _authedName;
}
void setPremiumRef(const QString &ref);
[[nodiscard]] QString premiumRef() const;
@ -605,6 +609,8 @@ private:
const std::unique_ptr<ChatHelpers::EmojiInteractions> _emojiInteractions;
const bool _isPrimary = false;
QString _authedName;
using SendingAnimation = Ui::MessageSendingAnimationController;
const std::unique_ptr<SendingAnimation> _sendingAnimation;