Add new tray icon options (#46)

* Update icon without restart
* Turn TDESKTOP_DISABLE_TRAY_COUNTER into option
* Fix custom icon for mac
* Turn KTGDESKTOP_USE_TELEGRAM_PANEL_ICON into option in setitngs
This commit is contained in:
ilya-fedin 2020-05-18 01:35:08 +04:00 committed by GitHub
parent 1b762e83ed
commit 79d3918210
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 137 additions and 55 deletions

View file

@ -2512,6 +2512,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ktg_settings_tray_icon_desc" = "If you don't like any of these icons, you can place icon.png in your profile folder.\n\nYou'll need to restart app to save changes.";
"ktg_settings_disable_tray_counter" = "Disable tray icon counter";
"ktg_settings_use_telegram_panel_icon" = "Ask the system for telegram icon";
"ktg_settings_chat_id" = "Chat ID in profile";
"ktg_settings_chat_id_desc" = "You can choose desired format here.\n\nTelegram API uses IDs as-is, but Bot API adds minus in the beginning for groups, and -100 for channels and supergroups to fit it in one field.\n\nIf you have profile panel opened, re-open it to see changes.";
"ktg_settings_chat_id_disable" = "Hide";

View file

@ -117,6 +117,8 @@
"ktg_settings_tray_icon_red": "Красная",
"ktg_settings_tray_icon_legacy": "Старая",
"ktg_settings_tray_icon_desc": "Если вам не нравится ни одна из этих иконок, вы можете положить icon.png в вашу папку профиля.\n\nДля применения и просмотра изменений требуется перезапуск.",
"ktg_settings_disable_tray_counter": "Отключить счетчик на иконке в трее",
"ktg_settings_use_telegram_panel_icon": "Запрашивать у системы иконку Telegram",
"ktg_settings_chat_id": "ID чата в профиле",
"ktg_settings_chat_id_desc": "Здесь можно выбрать желаемый вид ID.\n\nTelegram API использует ID как есть, а Bot API добавляет минус в начало для групп и -100 для каналов и супергрупп, чтобы уместить всё в одно поле.\n\nЕсли у вас открыта панель профиля, закройте её и откройте заново, чтобы увидеть изменения.",
"ktg_settings_chat_id_disable": "Скрыть",

View file

@ -189,6 +189,8 @@ QByteArray GenerateSettingsJson(bool areDefault = false) {
settings.insert(qsl("recent_stickers_limit"), RecentStickersLimit());
settings.insert(qsl("userpic_corner_type"), cUserpicCornersType());
settings.insert(qsl("always_show_top_userpic"), cShowTopBarUserpic());
settings.insert(qsl("disable_tray_counter"), cDisableTrayCounter());
settings.insert(qsl("use_telegram_panel_icon"), cUseTelegramPanelIcon());
settings.insert(qsl("custom_app_icon"), cCustomAppIcon());
settings.insert(qsl("profile_top_mute"), cProfileTopBarNotifications());
settings.insert(qsl("hover_emoji_panel"), HoverEmojiPanel());
@ -421,6 +423,14 @@ bool Manager::readCustomFile() {
cSetShowTopBarUserpic(v);
});
ReadBoolOption(settings, "disable_tray_counter", [&](auto v) {
cSetDisableTrayCounter(v);
});
ReadBoolOption(settings, "use_telegram_panel_icon", [&](auto v) {
cSetUseTelegramPanelIcon(v);
});
ReadIntOption(settings, "custom_app_icon", [&](auto v) {
if (v >= 0 && v <= 5) {
cSetCustomAppIcon(v);

View file

@ -134,6 +134,8 @@ rpl::producer<int> RecentStickersLimitChanges() {
int gUserpicCornersType = 3;
bool gShowTopBarUserpic = false;
bool gDisableTrayCounter = false;
bool gUseTelegramPanelIcon = false;
int gCustomAppIcon = 0;
int gDefaultFilterId = 0;

View file

@ -97,6 +97,8 @@ void SetRecentStickersLimit(int limit);
DeclareSetting(int, UserpicCornersType);
DeclareSetting(bool, ShowTopBarUserpic);
DeclareSetting(bool, DisableTrayCounter);
DeclareSetting(bool, UseTelegramPanelIcon);
DeclareSetting(int, CustomAppIcon);
DeclareSetting(int, DefaultFilterId);

View file

@ -399,6 +399,38 @@ void SetupKotatoSystem(not_null<Ui::VerticalLayout*> container) {
}, container->lifetime());
#endif // Q_OS_WIN || Q_OS_MAC
AddButton(
container,
tr::ktg_settings_disable_tray_counter(),
st::settingsButton
)->toggleOn(
rpl::single(cDisableTrayCounter())
)->toggledValue(
) | rpl::filter([](bool enabled) {
return (enabled != cDisableTrayCounter());
}) | rpl::start_with_next([](bool enabled) {
cSetDisableTrayCounter(enabled);
Notify::unreadCounterUpdated();
::Kotato::JsonSettings::Write();
}, container->lifetime());
#ifdef Q_OS_LINUX
AddButton(
container,
tr::ktg_settings_use_telegram_panel_icon(),
st::settingsButton
)->toggleOn(
rpl::single(cUseTelegramPanelIcon())
)->toggledValue(
) | rpl::filter([](bool enabled) {
return (enabled != cUseTelegramPanelIcon());
}) | rpl::start_with_next([](bool enabled) {
cSetUseTelegramPanelIcon(enabled);
Notify::unreadCounterUpdated();
::Kotato::JsonSettings::Write();
}, container->lifetime());
#endif // Q_OS_LINUX
const QMap<int, QString> trayIconOptions = {
{ 0, TrayIconLabel(0) },
{ 1, TrayIconLabel(1) },
@ -408,10 +440,18 @@ void SetupKotatoSystem(not_null<Ui::VerticalLayout*> container) {
{ 5, TrayIconLabel(5) },
};
auto trayIconText = rpl::single(
rpl::empty_value()
) | rpl::then(base::ObservableViewer(
Global::RefUnreadCounterUpdate()
)) | rpl::map([] {
return TrayIconLabel(cCustomAppIcon());
});
AddButtonWithLabel(
container,
tr::ktg_settings_tray_icon(),
rpl::single(TrayIconLabel(cCustomAppIcon())),
trayIconText,
st::settingsButton
)->addClickHandler([=] {
Ui::show(Box<::Kotato::RadioBox>(
@ -421,8 +461,9 @@ void SetupKotatoSystem(not_null<Ui::VerticalLayout*> container) {
trayIconOptions,
[=] (int value) {
cSetCustomAppIcon(value);
Notify::unreadCounterUpdated();
::Kotato::JsonSettings::Write();
}, true));
}, false));
});
AddSkip(container);

View file

@ -78,23 +78,7 @@ void FeedLangTestingKey(int key) {
MainWindow::MainWindow(not_null<Window::Controller*> controller)
: Platform::MainWindow(controller) {
QImage iconImage(cWorkingDir() + "tdata/icon.png");
auto logo = iconImage.isNull()
? Core::App().logo(cCustomAppIcon())
: iconImage;
icon16 = logo.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = logo.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = logo.scaledToWidth(64, Qt::SmoothTransformation);
auto logoNoMargin = iconImage.isNull()
? Core::App().logoNoMargin(cCustomAppIcon())
: iconImage;
iconbig16 = logoNoMargin.scaledToWidth(16, Qt::SmoothTransformation);
iconbig32 = logoNoMargin.scaledToWidth(32, Qt::SmoothTransformation);
iconbig64 = logoNoMargin.scaledToWidth(64, Qt::SmoothTransformation);
updateIconCache();
resize(st::windowDefaultWidth, st::windowDefaultHeight);
@ -959,6 +943,28 @@ void MainWindow::placeSmallCounter(QImage &img, int size, int count, style::colo
}
void MainWindow::updateIconCache() {
QImage iconImage(cWorkingDir() + "tdata/icon.png");
auto logo = iconImage.isNull()
? Core::App().logo(cCustomAppIcon())
: iconImage;
icon16 = logo.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = logo.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = logo.scaledToWidth(64, Qt::SmoothTransformation);
auto logoNoMargin = iconImage.isNull()
? Core::App().logoNoMargin(cCustomAppIcon())
: iconImage;
iconbig16 = logoNoMargin.scaledToWidth(16, Qt::SmoothTransformation);
iconbig32 = logoNoMargin.scaledToWidth(32, Qt::SmoothTransformation);
iconbig64 = logoNoMargin.scaledToWidth(64, Qt::SmoothTransformation);
_customIconId = cCustomAppIcon();
}
QImage MainWindow::iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) {
bool layer = false;
if (size < 0) {
@ -1016,6 +1022,10 @@ QImage MainWindow::iconWithCounter(int size, int count, style::color bg, style::
if (size != 16 && size != 32) size = 64;
}
if (_customIconId != cCustomAppIcon()) {
updateIconCache();
}
QImage img(smallIcon ? ((size == 16) ? iconbig16 : (size == 32 ? iconbig32 : iconbig64)) : ((size == 16) ? icon16 : (size == 32 ? icon32 : icon64)));
if (account().sessionExists() && account().session().supportMode()) {
Window::ConvertIconToBlack(img);

View file

@ -159,6 +159,7 @@ private:
void applyInitialWorkMode();
void ensureLayerCreated();
void destroyLayer();
void updateIconCache();
void themeUpdated(const Window::Theme::BackgroundUpdate &data);
@ -166,6 +167,7 @@ private:
void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override;
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
int _customIconId = 0;
crl::time _lastTrayClickTime = 0;
QPoint _lastMousePosition;

View file

@ -45,9 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform {
namespace {
constexpr auto kDisableTrayCounter = "TDESKTOP_DISABLE_TRAY_COUNTER"_cs;
constexpr auto kForcePanelIcon = "TDESKTOP_FORCE_PANEL_ICON"_cs;
constexpr auto kUseTelegramPanelIcon = "KTGDESKTOP_USE_TELEGRAM_PANEL_ICON"_cs;
constexpr auto kPanelTrayIconName = "kotatogram-panel"_cs;
constexpr auto kMutePanelTrayIconName = "kotatogram-mute-panel"_cs;
constexpr auto kAttentionPanelTrayIconName = "kotatogram-attention-panel"_cs;
@ -67,23 +65,22 @@ int32 TrayIconCount = 0;
base::flat_map<int, QImage> TrayIconImageBack;
QIcon TrayIcon;
QString TrayIconThemeName, TrayIconName;
int TrayIconCustomId = 0;
bool TrayIconCounterDisabled = false;
bool SNIAvailable = false;
bool AppMenuSupported = false;
QString GetPanelIconName(int counter, bool muted) {
const auto useTelegramIcon = qEnvironmentVariableIsSet(
kUseTelegramPanelIcon.utf8());
const auto iconName = useTelegramIcon
const auto iconName = cUseTelegramPanelIcon()
? kTelegramPanelTrayIconName.utf16()
: kPanelTrayIconName.utf16();
const auto muteIconName = useTelegramIcon
const auto muteIconName = cUseTelegramPanelIcon()
? kTelegramMutePanelTrayIconName.utf16()
: kMutePanelTrayIconName.utf16();
const auto attentionIconName = useTelegramIcon
const auto attentionIconName = cUseTelegramPanelIcon()
? kTelegramAttentionPanelTrayIconName.utf16()
: kAttentionPanelTrayIconName.utf16();
@ -125,7 +122,9 @@ bool IsIconRegenerationNeeded(
|| iconThemeName != TrayIconThemeName
|| iconName != TrayIconName
|| muted != TrayIconMuted
|| counterSlice != TrayIconCount;
|| counterSlice != TrayIconCount
|| cCustomAppIcon() != TrayIconCustomId
|| cDisableTrayCounter() != TrayIconCounterDisabled;
}
void UpdateIconRegenerationNeeded(
@ -141,6 +140,8 @@ void UpdateIconRegenerationNeeded(
TrayIconCount = counterSlice;
TrayIconThemeName = iconThemeName;
TrayIconName = iconName;
TrayIconCustomId = cCustomAppIcon();
TrayIconCounterDisabled = cDisableTrayCounter();
}
QIcon TrayIconGen(int counter, bool muted) {
@ -152,7 +153,7 @@ QIcon TrayIconGen(int counter, bool muted) {
const auto iconName = GetTrayIconName(counter, muted);
if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8())
if (cDisableTrayCounter()
&& !iconName.isEmpty()) {
const auto result = QIcon::fromTheme(iconName);
UpdateIconRegenerationNeeded(result, counter, muted, iconThemeName);
@ -177,7 +178,8 @@ QIcon TrayIconGen(int counter, bool muted) {
if (currentImageBack.isNull()
|| iconThemeName != TrayIconThemeName
|| iconName != TrayIconName) {
|| iconName != TrayIconName
|| cCustomAppIcon() != TrayIconCustomId) {
if (QFileInfo::exists(cWorkingDir() + "tdata/icon.png")) {
currentImageBack = QImage(cWorkingDir() + "tdata/icon.png");
} else if (cCustomAppIcon() != 0) {
@ -217,7 +219,7 @@ QIcon TrayIconGen(int counter, bool muted) {
auto iconImage = currentImageBack;
if (!qEnvironmentVariableIsSet(kDisableTrayCounter.utf8())
if (!cDisableTrayCounter()
&& counter > 0) {
QPainter p(&iconImage);
int32 layerSize = -16;
@ -523,7 +525,7 @@ void MainWindow::psTrayMenuUpdated() {
void MainWindow::setSNITrayIcon(int counter, bool muted) {
const auto iconName = GetTrayIconName(counter, muted);
if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8())
if (cDisableTrayCounter()
&& !iconName.isEmpty()
&& (!InSnap()
|| qEnvironmentVariableIsSet(kForcePanelIcon.utf8()))) {
@ -535,7 +537,8 @@ void MainWindow::setSNITrayIcon(int counter, bool muted) {
_sniTrayIcon->setToolTipIconByName(iconName);
} else if (IsIndicatorApplication()) {
if (!IsIconRegenerationNeeded(counter, muted)
&& !_sniTrayIcon->iconName().isEmpty()) {
&& _trayIconFile
&& _sniTrayIcon->iconName() == _trayIconFile->fileName()) {
return;
}
@ -548,7 +551,8 @@ void MainWindow::setSNITrayIcon(int counter, bool muted) {
}
} else {
if (!IsIconRegenerationNeeded(counter, muted)
&& !_sniTrayIcon->iconPixmap().isEmpty()) {
&& !_sniTrayIcon->iconPixmap().isEmpty()
&& _sniTrayIcon->iconName().isEmpty()) {
return;
}

View file

@ -458,8 +458,16 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
auto forceOpenGL = std::make_unique<QOpenGLWidget>(this);
#endif // !OS_MAC_OLD
trayImg = st::macTrayIcon.instance(QColor(0, 0, 0, 180), 100);
trayImgSel = st::macTrayIcon.instance(QColor(255, 255, 255), 100);
QImage iconImage(cWorkingDir() + "tdata/icon.png");
QImage iconImageSelected(cWorkingDir() + "tdata/icon_selected.png");
trayImg = iconImage.isNull()
? st::macTrayIcon.instance(QColor(0, 0, 0, 180), 100)
: iconImage;
trayImgSel = iconImageSelected.isNull()
? st::macTrayIcon.instance(QColor(255, 255, 255), 100)
: iconImageSelected;
_hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); });
@ -563,21 +571,9 @@ void MainWindow::psTrayMenuUpdated() {
void MainWindow::psSetupTrayIcon() {
if (!trayIcon) {
trayIcon = new QSystemTrayIcon(this);
QIcon icon;
QPixmap iconPixmap(cWorkingDir() + "tdata/icon.png");
QPixmap iconPixmapSelected(cWorkingDir() + "tdata/icon_selected.png");
if (!iconPixmap.isNull()) {
icon.addPixmap(iconPixmap);
} else {
icon.addPixmap(QPixmap::fromImage(psTrayIcon(), Qt::ColorOnly));
}
if (!iconPixmapSelected.isNull()) {
icon.addPixmap(iconPixmapSelected, QIcon::Selected);
} else {
icon.addPixmap(QPixmap::fromImage(psTrayIcon(true), Qt::ColorOnly), QIcon::Selected);
}
QIcon icon(QPixmap::fromImage(psTrayIcon(), Qt::ColorOnly));
icon.addPixmap(QPixmap::fromImage(psTrayIcon(true), Qt::ColorOnly), QIcon::Selected);
trayIcon->setIcon(icon);
attachToTrayIcon(trayIcon);
@ -666,9 +662,11 @@ void MainWindow::updateIconCounters() {
QImage img(psTrayIcon(dm)), imgsel(psTrayIcon(true));
img.detach();
imgsel.detach();
int32 size = 22 * cIntRetinaFactor();
_placeCounter(img, size, counter, bg, (dm && muted) ? st::trayCounterFgMacInvert : st::trayCounterFg);
_placeCounter(imgsel, size, counter, st::trayCounterBgMacInvert, st::trayCounterFgMacInvert);
if (!cDisableTrayCounter()) {
int32 size = 22 * cIntRetinaFactor();
_placeCounter(img, size, counter, bg, (dm && muted) ? st::trayCounterFgMacInvert : st::trayCounterFg);
_placeCounter(imgsel, size, counter, st::trayCounterBgMacInvert, st::trayCounterFgMacInvert);
}
icon.addPixmap(App::pixmapFromImageInPlace(std::move(img)));
icon.addPixmap(App::pixmapFromImageInPlace(std::move(imgsel)), QIcon::Selected);
trayIcon->setIcon(icon);

View file

@ -794,7 +794,13 @@ void MainWindow::updateIconCounters() {
if (trayIcon) {
// Force Qt to use right icon size, not the larger one.
QIcon forTrayIcon;
forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 ? iconSmallPixmap32 : iconSmallPixmap16);
auto forTrayIcon16 = cDisableTrayCounter()
? App::pixmapFromImageInPlace(iconWithCounter(16, 0, bg, fg, true))
: iconSmallPixmap16;
auto forTrayIcon32 = cDisableTrayCounter()
? App::pixmapFromImageInPlace(iconWithCounter(32, 0, bg, fg, true))
: iconSmallPixmap32;
forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 ? forTrayIcon32 : forTrayIcon16);
trayIcon->setIcon(forTrayIcon);
}

View file

@ -327,9 +327,10 @@ bool MainWindow::computeIsActive() const {
void MainWindow::updateWindowIcon() {
const auto supportIcon = account().sessionExists()
&& account().session().supportMode();
if (supportIcon != _usingSupportIcon || _icon.isNull()) {
if (supportIcon != _usingSupportIcon || _icon.isNull() || _customIconId != cCustomAppIcon()) {
_icon = CreateIcon(&account());
_usingSupportIcon = supportIcon;
_customIconId = cCustomAppIcon();
}
setWindowIcon(_icon);
}

View file

@ -192,6 +192,7 @@ private:
QIcon _icon;
bool _usingSupportIcon = false;
int _customIconId = 0;
QString _titleText;
bool _isActive = false;