mirror of https://github.com/procxx/kepka.git
				
				
				
			Native notifications switched off by default. Libnotify supported.
This commit is contained in:
		
							parent
							
								
									6db52f7fa9
								
							
						
					
					
						commit
						c9288f2d0a
					
				| 
						 | 
					@ -244,6 +244,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | 
				
			||||||
"lng_settings_show_name" = "Show sender's name";
 | 
					"lng_settings_show_name" = "Show sender's name";
 | 
				
			||||||
"lng_settings_show_preview" = "Show message preview";
 | 
					"lng_settings_show_preview" = "Show message preview";
 | 
				
			||||||
"lng_settings_use_windows" = "Use Windows notifications";
 | 
					"lng_settings_use_windows" = "Use Windows notifications";
 | 
				
			||||||
 | 
					"lng_settings_use_native_notifications" = "Use native notifications";
 | 
				
			||||||
"lng_settings_sound_notify" = "Play sound";
 | 
					"lng_settings_sound_notify" = "Play sound";
 | 
				
			||||||
"lng_settings_include_muted" = "Include muted chats in unread count";
 | 
					"lng_settings_include_muted" = "Include muted chats in unread count";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -634,7 +634,7 @@ struct Data {
 | 
				
			||||||
	bool RestoreSoundNotifyFromTray = false;
 | 
						bool RestoreSoundNotifyFromTray = false;
 | 
				
			||||||
	bool IncludeMuted = true;
 | 
						bool IncludeMuted = true;
 | 
				
			||||||
	DBINotifyView NotifyView = dbinvShowPreview;
 | 
						DBINotifyView NotifyView = dbinvShowPreview;
 | 
				
			||||||
	bool WindowsNotifications = true;
 | 
						bool NativeNotifications = false;
 | 
				
			||||||
	base::Observable<Notify::ChangeType> NotifySettingsChanged;
 | 
						base::Observable<Notify::ChangeType> NotifySettingsChanged;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DBIConnectionType ConnectionType = dbictAuto;
 | 
						DBIConnectionType ConnectionType = dbictAuto;
 | 
				
			||||||
| 
						 | 
					@ -741,7 +741,7 @@ DefineVar(Global, bool, DesktopNotify);
 | 
				
			||||||
DefineVar(Global, bool, RestoreSoundNotifyFromTray);
 | 
					DefineVar(Global, bool, RestoreSoundNotifyFromTray);
 | 
				
			||||||
DefineVar(Global, bool, IncludeMuted);
 | 
					DefineVar(Global, bool, IncludeMuted);
 | 
				
			||||||
DefineVar(Global, DBINotifyView, NotifyView);
 | 
					DefineVar(Global, DBINotifyView, NotifyView);
 | 
				
			||||||
DefineVar(Global, bool, WindowsNotifications);
 | 
					DefineVar(Global, bool, NativeNotifications);
 | 
				
			||||||
DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
 | 
					DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DefineVar(Global, DBIConnectionType, ConnectionType);
 | 
					DefineVar(Global, DBIConnectionType, ConnectionType);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,7 +307,7 @@ DeclareVar(bool, DesktopNotify);
 | 
				
			||||||
DeclareVar(bool, RestoreSoundNotifyFromTray);
 | 
					DeclareVar(bool, RestoreSoundNotifyFromTray);
 | 
				
			||||||
DeclareVar(bool, IncludeMuted);
 | 
					DeclareVar(bool, IncludeMuted);
 | 
				
			||||||
DeclareVar(DBINotifyView, NotifyView);
 | 
					DeclareVar(DBINotifyView, NotifyView);
 | 
				
			||||||
DeclareVar(bool, WindowsNotifications);
 | 
					DeclareVar(bool, NativeNotifications);
 | 
				
			||||||
DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
 | 
					DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DeclareVar(DBIConnectionType, ConnectionType);
 | 
					DeclareVar(DBIConnectionType, ConnectionType);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -534,7 +534,7 @@ enum {
 | 
				
			||||||
	dbiDcOption = 0x27,
 | 
						dbiDcOption = 0x27,
 | 
				
			||||||
	dbiTryIPv6 = 0x28,
 | 
						dbiTryIPv6 = 0x28,
 | 
				
			||||||
	dbiSongVolume = 0x29,
 | 
						dbiSongVolume = 0x29,
 | 
				
			||||||
	dbiWindowsNotifications = 0x30,
 | 
						dbiWindowsNotificationsOld = 0x30,
 | 
				
			||||||
	dbiIncludeMuted = 0x31,
 | 
						dbiIncludeMuted = 0x31,
 | 
				
			||||||
	dbiMegagroupSizeMax = 0x32,
 | 
						dbiMegagroupSizeMax = 0x32,
 | 
				
			||||||
	dbiDownloadPath = 0x33,
 | 
						dbiDownloadPath = 0x33,
 | 
				
			||||||
| 
						 | 
					@ -548,6 +548,7 @@ enum {
 | 
				
			||||||
	dbiModerateMode = 0x41,
 | 
						dbiModerateMode = 0x41,
 | 
				
			||||||
	dbiVideoVolume = 0x42,
 | 
						dbiVideoVolume = 0x42,
 | 
				
			||||||
	dbiStickersRecentLimit = 0x43,
 | 
						dbiStickersRecentLimit = 0x43,
 | 
				
			||||||
 | 
						dbiNativeNotifications = 0x44,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dbiEncryptedWithSalt = 333,
 | 
						dbiEncryptedWithSalt = 333,
 | 
				
			||||||
	dbiEncrypted = 444,
 | 
						dbiEncrypted = 444,
 | 
				
			||||||
| 
						 | 
					@ -989,12 +990,18 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
 | 
				
			||||||
		if (App::wnd()) App::wnd()->updateTrayMenu();
 | 
							if (App::wnd()) App::wnd()->updateTrayMenu();
 | 
				
			||||||
	} break;
 | 
						} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case dbiWindowsNotifications: {
 | 
						case dbiWindowsNotificationsOld: {
 | 
				
			||||||
 | 
							qint32 v;
 | 
				
			||||||
 | 
							stream >> v;
 | 
				
			||||||
 | 
							if (!_checkStreamStatus(stream)) return false;
 | 
				
			||||||
 | 
						} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case dbiNativeNotifications: {
 | 
				
			||||||
		qint32 v;
 | 
							qint32 v;
 | 
				
			||||||
		stream >> v;
 | 
							stream >> v;
 | 
				
			||||||
		if (!_checkStreamStatus(stream)) return false;
 | 
							if (!_checkStreamStatus(stream)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Global::SetWindowsNotifications(v == 1);
 | 
							Global::SetNativeNotifications(v == 1);
 | 
				
			||||||
	} break;
 | 
						} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case dbiWorkMode: {
 | 
						case dbiWorkMode: {
 | 
				
			||||||
| 
						 | 
					@ -1589,7 +1596,7 @@ void _writeUserSettings() {
 | 
				
			||||||
	data.stream << quint32(dbiShowingSavedGifs) << qint32(cShowingSavedGifs());
 | 
						data.stream << quint32(dbiShowingSavedGifs) << qint32(cShowingSavedGifs());
 | 
				
			||||||
	data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify());
 | 
						data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify());
 | 
				
			||||||
	data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView());
 | 
						data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView());
 | 
				
			||||||
	data.stream << quint32(dbiWindowsNotifications) << qint32(Global::WindowsNotifications());
 | 
						data.stream << quint32(dbiNativeNotifications) << qint32(Global::NativeNotifications());
 | 
				
			||||||
	data.stream << quint32(dbiAskDownloadPath) << qint32(Global::AskDownloadPath());
 | 
						data.stream << quint32(dbiAskDownloadPath) << qint32(Global::AskDownloadPath());
 | 
				
			||||||
	data.stream << quint32(dbiDownloadPath) << (Global::AskDownloadPath() ? QString() : Global::DownloadPath()) << (Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
 | 
						data.stream << quint32(dbiDownloadPath) << (Global::AskDownloadPath() ? QString() : Global::DownloadPath()) << (Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
 | 
				
			||||||
	data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
 | 
						data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,11 @@ void startLibNotify() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QLibrary lib_notify;
 | 
						QLibrary lib_notify;
 | 
				
			||||||
	if (!loadLibrary(lib_notify, "notify", 4)) {
 | 
						if (!loadLibrary(lib_notify, "notify", 4)) {
 | 
				
			||||||
		return;
 | 
							if (!loadLibrary(lib_notify, "notify", 5)) {
 | 
				
			||||||
 | 
								if (!loadLibrary(lib_notify, "notify", 1)) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	load(lib_notify, "notify_init", notify_init);
 | 
						load(lib_notify, "notify_init", notify_init);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,10 +93,16 @@ bool setupGtkBase(QLibrary &lib_gtk) {
 | 
				
			||||||
	if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
 | 
						if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
 | 
				
			||||||
	if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
 | 
						if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
 | 
				
			||||||
	if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
 | 
						if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
 | 
				
			||||||
 | 
						if (!load(lib_gtk, "g_signal_handler_disconnect", g_signal_handler_disconnect)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
 | 
						if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
 | 
				
			||||||
	if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
 | 
						if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
 | 
				
			||||||
	if (!load(lib_gtk, "g_free", g_free)) return false;
 | 
						if (!load(lib_gtk, "g_free", g_free)) return false;
 | 
				
			||||||
 | 
						if (!load(lib_gtk, "g_list_foreach", g_list_foreach)) return false;
 | 
				
			||||||
 | 
						if (!load(lib_gtk, "g_list_free", g_list_free)) return false;
 | 
				
			||||||
 | 
						if (!load(lib_gtk, "g_list_free_full", g_list_free_full)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!load(lib_gtk, "g_error_free", g_error_free)) return false;
 | 
				
			||||||
	if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
 | 
						if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DEBUG_LOG(("Library gtk functions loaded!"));
 | 
						DEBUG_LOG(("Library gtk functions loaded!"));
 | 
				
			||||||
| 
						 | 
					@ -170,6 +176,7 @@ f_gtk_dialog_run gtk_dialog_run = nullptr;
 | 
				
			||||||
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
 | 
					f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
 | 
				
			||||||
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
 | 
					f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
 | 
				
			||||||
f_g_signal_connect_data g_signal_connect_data = nullptr;
 | 
					f_g_signal_connect_data g_signal_connect_data = nullptr;
 | 
				
			||||||
 | 
					f_g_signal_handler_disconnect g_signal_handler_disconnect = nullptr;
 | 
				
			||||||
f_app_indicator_new app_indicator_new = nullptr;
 | 
					f_app_indicator_new app_indicator_new = nullptr;
 | 
				
			||||||
f_app_indicator_set_status app_indicator_set_status = nullptr;
 | 
					f_app_indicator_set_status app_indicator_set_status = nullptr;
 | 
				
			||||||
f_app_indicator_set_menu app_indicator_set_menu = nullptr;
 | 
					f_app_indicator_set_menu app_indicator_set_menu = nullptr;
 | 
				
			||||||
| 
						 | 
					@ -193,6 +200,10 @@ f_g_object_ref_sink g_object_ref_sink = nullptr;
 | 
				
			||||||
f_g_object_unref g_object_unref = nullptr;
 | 
					f_g_object_unref g_object_unref = nullptr;
 | 
				
			||||||
f_g_idle_add g_idle_add = nullptr;
 | 
					f_g_idle_add g_idle_add = nullptr;
 | 
				
			||||||
f_g_free g_free = nullptr;
 | 
					f_g_free g_free = nullptr;
 | 
				
			||||||
 | 
					f_g_list_foreach g_list_foreach = nullptr;
 | 
				
			||||||
 | 
					f_g_list_free g_list_free = nullptr;
 | 
				
			||||||
 | 
					f_g_list_free_full g_list_free_full = nullptr;
 | 
				
			||||||
 | 
					f_g_error_free g_error_free = nullptr;
 | 
				
			||||||
f_g_slist_free g_slist_free = nullptr;
 | 
					f_g_slist_free g_slist_free = nullptr;
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
 | 
					f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,6 +255,9 @@ inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *de
 | 
				
			||||||
	return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED);
 | 
						return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*f_g_signal_handler_disconnect)(gpointer instance, gulong handler_id);
 | 
				
			||||||
 | 
					extern f_g_signal_handler_disconnect g_signal_handler_disconnect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
 | 
					typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
 | 
				
			||||||
extern f_app_indicator_new app_indicator_new;
 | 
					extern f_app_indicator_new app_indicator_new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,6 +327,18 @@ extern f_g_idle_add g_idle_add;
 | 
				
			||||||
typedef void (*f_g_free)(gpointer mem);
 | 
					typedef void (*f_g_free)(gpointer mem);
 | 
				
			||||||
extern f_g_free g_free;
 | 
					extern f_g_free g_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*f_g_list_foreach)(GList *list, GFunc func, gpointer user_data);
 | 
				
			||||||
 | 
					extern f_g_list_foreach g_list_foreach;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*f_g_list_free)(GList *list);
 | 
				
			||||||
 | 
					extern f_g_list_free g_list_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*f_g_list_free_full)(GList *list, GDestroyNotify free_func);
 | 
				
			||||||
 | 
					extern f_g_list_free_full g_list_free_full;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*f_g_error_free)(GError *error);
 | 
				
			||||||
 | 
					extern f_g_error_free g_error_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*f_g_slist_free)(GSList *list);
 | 
					typedef void (*f_g_slist_free)(GSList *list);
 | 
				
			||||||
extern f_g_slist_free g_slist_free;
 | 
					extern f_g_slist_free g_slist_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | 
				
			||||||
#include "platform/linux/main_window_linux.h"
 | 
					#include "platform/linux/main_window_linux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "platform/linux/linux_libs.h"
 | 
					#include "platform/linux/linux_libs.h"
 | 
				
			||||||
 | 
					#include "platform/platform_notifications_manager.h"
 | 
				
			||||||
#include "mainwindow.h"
 | 
					#include "mainwindow.h"
 | 
				
			||||||
#include "application.h"
 | 
					#include "application.h"
 | 
				
			||||||
#include "lang.h"
 | 
					#include "lang.h"
 | 
				
			||||||
| 
						 | 
					@ -355,6 +356,10 @@ void MainWindow::psUpdateCounter() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MainWindow::psHasNativeNotifications() {
 | 
				
			||||||
 | 
						return Notifications::supported();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::LibsLoaded() {
 | 
					void MainWindow::LibsLoaded() {
 | 
				
			||||||
	QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
 | 
						QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
 | 
				
			||||||
	noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
 | 
						noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,9 +58,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void psUpdateCounter();
 | 
						void psUpdateCounter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool psHasNativeNotifications() {
 | 
						bool psHasNativeNotifications();
 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
 | 
						virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | 
				
			||||||
#include "window/notifications_utilities.h"
 | 
					#include "window/notifications_utilities.h"
 | 
				
			||||||
#include "platform/linux/linux_libnotify.h"
 | 
					#include "platform/linux/linux_libnotify.h"
 | 
				
			||||||
#include "platform/linux/linux_libs.h"
 | 
					#include "platform/linux/linux_libs.h"
 | 
				
			||||||
 | 
					#include "lang.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Platform {
 | 
					namespace Platform {
 | 
				
			||||||
namespace Notifications {
 | 
					namespace Notifications {
 | 
				
			||||||
| 
						 | 
					@ -31,7 +32,7 @@ namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NeverFreedPointer<Manager> ManagerInstance;
 | 
					NeverFreedPointer<Manager> ManagerInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool supported() {
 | 
					bool LibNotifyLoaded() {
 | 
				
			||||||
	return (Libs::notify_init != nullptr)
 | 
						return (Libs::notify_init != nullptr)
 | 
				
			||||||
		&& (Libs::notify_uninit != nullptr)
 | 
							&& (Libs::notify_uninit != nullptr)
 | 
				
			||||||
		&& (Libs::notify_is_initted != nullptr)
 | 
							&& (Libs::notify_is_initted != nullptr)
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,7 @@ bool supported() {
 | 
				
			||||||
		&& (Libs::notify_notification_update != nullptr)
 | 
							&& (Libs::notify_notification_update != nullptr)
 | 
				
			||||||
		&& (Libs::notify_notification_show != nullptr)
 | 
							&& (Libs::notify_notification_show != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_app_name != nullptr)
 | 
					//		&& (Libs::notify_notification_set_app_name != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_timeout != nullptr)
 | 
							&& (Libs::notify_notification_set_timeout != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_category != nullptr)
 | 
					//		&& (Libs::notify_notification_set_category != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_urgency != nullptr)
 | 
					//		&& (Libs::notify_notification_set_urgency != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_icon_from_pixbuf != nullptr)
 | 
					//		&& (Libs::notify_notification_set_icon_from_pixbuf != nullptr)
 | 
				
			||||||
| 
						 | 
					@ -52,23 +53,139 @@ bool supported() {
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_int32 != nullptr)
 | 
					//		&& (Libs::notify_notification_set_hint_int32 != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_uint32 != nullptr)
 | 
					//		&& (Libs::notify_notification_set_hint_uint32 != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_double != nullptr)
 | 
					//		&& (Libs::notify_notification_set_hint_double != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_string != nullptr)
 | 
							&& (Libs::notify_notification_set_hint_string != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_byte != nullptr)
 | 
					//		&& (Libs::notify_notification_set_hint_byte != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_set_hint_byte_array != nullptr)
 | 
					//		&& (Libs::notify_notification_set_hint_byte_array != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_clear_hints != nullptr)
 | 
					//		&& (Libs::notify_notification_clear_hints != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_add_action != nullptr)
 | 
							&& (Libs::notify_notification_add_action != nullptr)
 | 
				
			||||||
//		&& (Libs::notify_notification_clear_actions != nullptr)
 | 
							&& (Libs::notify_notification_clear_actions != nullptr)
 | 
				
			||||||
		&& (Libs::notify_notification_close != nullptr)
 | 
							&& (Libs::notify_notification_close != nullptr)
 | 
				
			||||||
		&& (Libs::notify_notification_get_closed_reason != nullptr)
 | 
							&& (Libs::notify_notification_get_closed_reason != nullptr)
 | 
				
			||||||
 | 
							&& (Libs::g_object_ref_sink != nullptr)
 | 
				
			||||||
		&& (Libs::g_object_unref != nullptr)
 | 
							&& (Libs::g_object_unref != nullptr)
 | 
				
			||||||
 | 
							&& (Libs::g_list_free_full != nullptr)
 | 
				
			||||||
 | 
							&& (Libs::g_error_free != nullptr)
 | 
				
			||||||
 | 
							&& (Libs::g_signal_connect_data != nullptr)
 | 
				
			||||||
 | 
							&& (Libs::g_signal_handler_disconnect != nullptr)
 | 
				
			||||||
//		&& (Libs::gdk_pixbuf_new_from_data != nullptr)
 | 
					//		&& (Libs::gdk_pixbuf_new_from_data != nullptr)
 | 
				
			||||||
		&& (Libs::gdk_pixbuf_new_from_file != nullptr);
 | 
							&& (Libs::gdk_pixbuf_new_from_file != nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString escapeNotificationHtml(QString text) {
 | 
				
			||||||
 | 
						text = text.replace(QChar('<'), qstr("<"));
 | 
				
			||||||
 | 
						text = text.replace(QChar('>'), qstr(">"));
 | 
				
			||||||
 | 
						text = text.replace(QChar('&'), qstr("&"));
 | 
				
			||||||
 | 
						return text;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotificationData {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						NotificationData(const QString &title, const QString &body, PeerId peerId, MsgId msgId)
 | 
				
			||||||
 | 
						: _data(Libs::notify_notification_new(title.toUtf8().constData(), body.toUtf8().constData(), nullptr))
 | 
				
			||||||
 | 
						, _peerId(peerId)
 | 
				
			||||||
 | 
						, _msgId(msgId) {
 | 
				
			||||||
 | 
							if (valid()) {
 | 
				
			||||||
 | 
								init();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bool valid() const {
 | 
				
			||||||
 | 
							return (_data != nullptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						NotificationData(const NotificationData &other) = delete;
 | 
				
			||||||
 | 
						NotificationData &operator=(const NotificationData &other) = delete;
 | 
				
			||||||
 | 
						NotificationData(NotificationData &&other) = delete;
 | 
				
			||||||
 | 
						NotificationData &operator=(NotificationData &&other) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void setImage(const QString &imagePath) {
 | 
				
			||||||
 | 
							auto imagePathNative = QFile::encodeName(imagePath);
 | 
				
			||||||
 | 
							if (auto pixbuf = Libs::gdk_pixbuf_new_from_file(imagePathNative.constData(), nullptr)) {
 | 
				
			||||||
 | 
								Libs::notify_notification_set_image_from_pixbuf(_data, pixbuf);
 | 
				
			||||||
 | 
								Libs::g_object_unref(Libs::g_object_cast(pixbuf));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bool show() {
 | 
				
			||||||
 | 
							if (valid()) {
 | 
				
			||||||
 | 
								GError *error = nullptr;
 | 
				
			||||||
 | 
								Libs::notify_notification_show(_data, &error);
 | 
				
			||||||
 | 
								if (!error) {
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								logError(error);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool close() {
 | 
				
			||||||
 | 
							if (valid()) {
 | 
				
			||||||
 | 
								GError *error = nullptr;
 | 
				
			||||||
 | 
								Libs::notify_notification_close(_data, &error);
 | 
				
			||||||
 | 
								if (!error) {
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								logError(error);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						~NotificationData() {
 | 
				
			||||||
 | 
							if (valid()) {
 | 
				
			||||||
 | 
								if (_handlerId > 0) {
 | 
				
			||||||
 | 
									Libs::g_signal_handler_disconnect(Libs::g_object_cast(_data), _handlerId);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Libs::notify_notification_clear_actions(_data);
 | 
				
			||||||
 | 
								Libs::g_object_unref(Libs::g_object_cast(_data));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void init() {
 | 
				
			||||||
 | 
							_handlerId = Libs::g_signal_connect_helper(Libs::g_object_cast(_data), "closed", G_CALLBACK(NotificationData::notificationClosed), this);
 | 
				
			||||||
 | 
							Libs::notify_notification_set_timeout(_data, Libs::NOTIFY_EXPIRES_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (auto manager = ManagerInstance.data()) {
 | 
				
			||||||
 | 
								if (manager->hasActionsSupport()) {
 | 
				
			||||||
 | 
									Libs::notify_notification_add_action(_data, "default", lang(lng_context_reply_msg).toUtf8().constData(), NotificationData::notificationClicked, this, nullptr);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void onClose() {
 | 
				
			||||||
 | 
							if (auto manager = ManagerInstance.data()) {
 | 
				
			||||||
 | 
								manager->clearNotification(_peerId, _msgId);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void onClick() {
 | 
				
			||||||
 | 
							if (auto manager = ManagerInstance.data()) {
 | 
				
			||||||
 | 
								manager->notificationActivated(_peerId, _msgId);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void logError(GError *error) {
 | 
				
			||||||
 | 
							LOG(("LibNotify Error: domain %1, code %2, message '%3'").arg(error->domain).arg(error->code).arg(QString::fromUtf8(error->message)));
 | 
				
			||||||
 | 
							Libs::g_error_free(error);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void notificationClosed(Libs::NotifyNotification *notification, gpointer data) {
 | 
				
			||||||
 | 
							static_cast<NotificationData*>(data)->onClose();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						static void notificationClicked(Libs::NotifyNotification *notification, char *action, gpointer data) {
 | 
				
			||||||
 | 
							static_cast<NotificationData*>(data)->onClick();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Libs::NotifyNotification *_data = nullptr;
 | 
				
			||||||
 | 
						PeerId _peerId = 0;
 | 
				
			||||||
 | 
						MsgId _msgId = 0;
 | 
				
			||||||
 | 
						gulong _handlerId = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Notification = QSharedPointer<NotificationData>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void start() {
 | 
					void start() {
 | 
				
			||||||
	if (supported()) {
 | 
						if (LibNotifyLoaded()) {
 | 
				
			||||||
		if (Libs::notify_is_initted() || Libs::notify_init("Telegram Desktop")) {
 | 
							if (Libs::notify_is_initted() || Libs::notify_init("Telegram Desktop")) {
 | 
				
			||||||
			ManagerInstance.makeIfNull();
 | 
								ManagerInstance.makeIfNull();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -76,7 +193,14 @@ void start() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Manager *manager() {
 | 
					Manager *manager() {
 | 
				
			||||||
	return ManagerInstance.data();
 | 
						if (Global::NativeNotifications()) {
 | 
				
			||||||
 | 
							return ManagerInstance.data();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool supported() {
 | 
				
			||||||
 | 
						return ManagerInstance.data() != nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void finish() {
 | 
					void finish() {
 | 
				
			||||||
| 
						 | 
					@ -88,131 +212,214 @@ void finish() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Manager::Impl {
 | 
					class Manager::Impl {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
						Impl();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton);
 | 
						void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton);
 | 
				
			||||||
	void clearAll();
 | 
						void clearAll();
 | 
				
			||||||
	void clearFromHistory(History *history);
 | 
						void clearFromHistory(History *history);
 | 
				
			||||||
 | 
						void clearNotification(PeerId peerId, MsgId msgId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool hasPoorSupport() const {
 | 
				
			||||||
 | 
							return _poorSupported;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bool hasActionsSupport() const {
 | 
				
			||||||
 | 
							return _actionsSupported;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	static void notificationClosed(Libs::NotifyNotification *notification, gpointer data);
 | 
						void showNextNotification();
 | 
				
			||||||
	void clearNotification(Libs::NotifyNotification *notification);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	using Notifications = QMap<PeerId, QMap<MsgId, Libs::NotifyNotification*>>;
 | 
						struct QueuedNotification {
 | 
				
			||||||
 | 
							PeerData *peer = nullptr;
 | 
				
			||||||
 | 
							MsgId msgId = 0;
 | 
				
			||||||
 | 
							QString title;
 | 
				
			||||||
 | 
							QString body;
 | 
				
			||||||
 | 
							bool showUserpic = false;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using QueuedNotifications = QList<QueuedNotification>;
 | 
				
			||||||
 | 
						QueuedNotifications _queuedNotifications;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using Notifications = QMap<PeerId, QMap<MsgId, Notification>>;
 | 
				
			||||||
	Notifications _notifications;
 | 
						Notifications _notifications;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	using NotificationsData = QMap<Libs::NotifyNotification*, QPair<PeerId, MsgId>>;
 | 
					 | 
				
			||||||
	NotificationsData _notificationsData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Window::Notifications::CachedUserpics _cachedUserpics;
 | 
						Window::Notifications::CachedUserpics _cachedUserpics;
 | 
				
			||||||
 | 
						bool _actionsSupported = false;
 | 
				
			||||||
 | 
						bool _poorSupported = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::Impl::notificationClosed(Libs::NotifyNotification *notification, gpointer data) {
 | 
					void FreeCapability(void *ptr, void *data) {
 | 
				
			||||||
	if (auto manager = ManagerInstance.data()) {
 | 
						Libs::g_free(ptr);
 | 
				
			||||||
		manager->_impl->clearNotification(notification);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::Impl::clearNotification(Libs::NotifyNotification *notification) {
 | 
					Manager::Impl::Impl() {
 | 
				
			||||||
	auto dataIt = _notificationsData.find(notification);
 | 
						if (auto capabilities = Libs::notify_get_server_caps()) {
 | 
				
			||||||
	if (dataIt == _notificationsData.cend()) {
 | 
							for (auto capability = capabilities; capability; capability = capability->next) {
 | 
				
			||||||
		return;
 | 
								if (QString::fromUtf8(static_cast<const char*>(capability->data)) == qstr("actions")) {
 | 
				
			||||||
 | 
									_actionsSupported = true;
 | 
				
			||||||
 | 
						            break;
 | 
				
			||||||
 | 
						        }
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    Libs::g_list_free_full(capabilities, g_free);
 | 
				
			||||||
 | 
						    Libs::g_list_free(capabilities);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto peerId = dataIt->first;
 | 
						// Unity and other Notify OSD users handle desktop notifications
 | 
				
			||||||
	auto msgId = dataIt->second;
 | 
						// extremely poor, even without the ability to close() them.
 | 
				
			||||||
	_notificationsData.erase(dataIt);
 | 
						gchar *name = nullptr;
 | 
				
			||||||
 | 
						if (Libs::notify_get_server_info(&name, nullptr, nullptr, nullptr)) {
 | 
				
			||||||
	auto i = _notifications.find(peerId);
 | 
							if (name) {
 | 
				
			||||||
	if (i != _notifications.cend()) {
 | 
								auto serverName = QString::fromUtf8(static_cast<const char*>(name));
 | 
				
			||||||
		auto it = i.value().find(msgId);
 | 
								LOG(("Notifications Server: %1").arg(serverName));
 | 
				
			||||||
		if (it != i.value().cend()) {
 | 
								if (serverName == qstr("notify-osd")) {
 | 
				
			||||||
			Libs::g_object_unref(Libs::g_object_cast(it.value()));
 | 
									_actionsSupported = false;
 | 
				
			||||||
			i.value().erase(it);
 | 
					 | 
				
			||||||
			if (i.value().isEmpty()) {
 | 
					 | 
				
			||||||
				_notifications.erase(i);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								Libs::g_free(name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (!_actionsSupported) {
 | 
				
			||||||
 | 
							_poorSupported = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
 | 
					void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
 | 
				
			||||||
	auto titleUtf8 = title.toUtf8();
 | 
						auto titleText = escapeNotificationHtml(title);
 | 
				
			||||||
	auto bodyUtf8 = (subtitle.isEmpty() ? msg : ("<b>" + subtitle + "</b>\n" + msg)).toUtf8();
 | 
						auto bodyText = subtitle.isEmpty() ? escapeNotificationHtml(msg) : ("<b>" + escapeNotificationHtml(subtitle) + "</b>\n" + escapeNotificationHtml(msg));
 | 
				
			||||||
	auto notification = Libs::notify_notification_new(titleUtf8.constData(), bodyUtf8.constData(), nullptr);
 | 
					
 | 
				
			||||||
	if (!notification) {
 | 
						QueuedNotification notification;
 | 
				
			||||||
 | 
						notification.peer = peer;
 | 
				
			||||||
 | 
						notification.msgId = msgId;
 | 
				
			||||||
 | 
						notification.title = titleText;
 | 
				
			||||||
 | 
						notification.body = bodyText;
 | 
				
			||||||
 | 
						notification.showUserpic = showUserpic;
 | 
				
			||||||
 | 
						_queuedNotifications.push_back(notification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showNextNotification();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Manager::Impl::showNextNotification() {
 | 
				
			||||||
 | 
						// Show only one notification at a time in Unity / Notify OSD.
 | 
				
			||||||
 | 
						if (_poorSupported) {
 | 
				
			||||||
 | 
							for (auto b = _notifications.begin(); !_notifications.isEmpty() && b->isEmpty();) {
 | 
				
			||||||
 | 
								_notifications.erase(b);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!_notifications.isEmpty()) {
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QueuedNotification data;
 | 
				
			||||||
 | 
						while (!_queuedNotifications.isEmpty()) {
 | 
				
			||||||
 | 
							data = _queuedNotifications.front();
 | 
				
			||||||
 | 
							_queuedNotifications.pop_front();
 | 
				
			||||||
 | 
							if (data.peer) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!data.peer) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Libs::g_signal_connect_helper(Libs::g_object_cast(notification), "closed", G_CALLBACK(Manager::Impl::notificationClosed), peer);
 | 
						auto peerId = data.peer->id;
 | 
				
			||||||
 | 
						auto msgId = data.msgId;
 | 
				
			||||||
 | 
						auto notification = MakeShared<NotificationData>(data.title, data.body, peerId, msgId);
 | 
				
			||||||
 | 
						if (!notification->valid()) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	StorageKey key;
 | 
						StorageKey key;
 | 
				
			||||||
	if (showUserpic) {
 | 
						if (data.showUserpic) {
 | 
				
			||||||
		key = peer->userpicUniqueKey();
 | 
							key = data.peer->userpicUniqueKey();
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		key = StorageKey(0, 0);
 | 
							key = StorageKey(0, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto userpicPath = _cachedUserpics.get(key, peer);
 | 
						notification->setImage(_cachedUserpics.get(key, data.peer));
 | 
				
			||||||
	auto userpicPathNative = QFile::encodeName(userpicPath);
 | 
					 | 
				
			||||||
	if (auto pixbuf = Libs::gdk_pixbuf_new_from_file(userpicPathNative.constData(), nullptr)) {
 | 
					 | 
				
			||||||
		Libs::notify_notification_set_image_from_pixbuf(notification, pixbuf);
 | 
					 | 
				
			||||||
		Libs::g_object_unref(Libs::g_object_cast(pixbuf));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto i = _notifications.find(peer->id);
 | 
						auto i = _notifications.find(peerId);
 | 
				
			||||||
	if (i != _notifications.cend()) {
 | 
						if (i != _notifications.cend()) {
 | 
				
			||||||
		auto j = i->find(msgId);
 | 
							auto j = i->find(msgId);
 | 
				
			||||||
		if (j != i->cend()) {
 | 
							if (j != i->cend()) {
 | 
				
			||||||
			auto oldNotification = j.value();
 | 
								auto oldNotification = j.value();
 | 
				
			||||||
			i->erase(j);
 | 
								i->erase(j);
 | 
				
			||||||
			_notificationsData.remove(oldNotification);
 | 
								oldNotification->close();
 | 
				
			||||||
			Libs::notify_notification_close(oldNotification, nullptr);
 | 
								i = _notifications.find(peerId);
 | 
				
			||||||
			Libs::g_object_unref(Libs::g_object_cast(oldNotification));
 | 
					 | 
				
			||||||
			i = _notifications.find(peer->id);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (i == _notifications.cend()) {
 | 
						if (i == _notifications.cend()) {
 | 
				
			||||||
		i = _notifications.insert(peer->id, QMap<MsgId, Libs::NotifyNotification*>());
 | 
							i = _notifications.insert(peerId, QMap<MsgId, Notification>());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto result = Libs::notify_notification_show(notification, nullptr);
 | 
						_notifications[peerId].insert(msgId, notification);
 | 
				
			||||||
	if (!result) {
 | 
						if (!notification->show()) {
 | 
				
			||||||
		Libs::g_object_unref(Libs::g_object_cast(notification));
 | 
							i = _notifications.find(peerId);
 | 
				
			||||||
		i = _notifications.find(peer->id);
 | 
							if (i != _notifications.cend()) {
 | 
				
			||||||
		if (i != _notifications.cend() && i->isEmpty()) _notifications.erase(i);
 | 
								i->remove(msgId);
 | 
				
			||||||
		return;
 | 
								if (i->isEmpty()) _notifications.erase(i);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							showNextNotification();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_notifications[peer->id].insert(msgId, notification);
 | 
					 | 
				
			||||||
	_notificationsData.insert(notification, qMakePair(peer->id, msgId));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::Impl::clearAll() {
 | 
					void Manager::Impl::clearAll() {
 | 
				
			||||||
	_notificationsData.clear();
 | 
						_queuedNotifications.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto temp = createAndSwap(_notifications);
 | 
						auto temp = createAndSwap(_notifications);
 | 
				
			||||||
	for_const (auto ¬ifications, temp) {
 | 
						for_const (auto ¬ifications, temp) {
 | 
				
			||||||
		for_const (auto notification, notifications) {
 | 
							for_const (auto notification, notifications) {
 | 
				
			||||||
			Libs::notify_notification_close(notification, nullptr);
 | 
								notification->close();
 | 
				
			||||||
			Libs::g_object_unref(Libs::g_object_cast(notification));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::Impl::clearFromHistory(History *history) {
 | 
					void Manager::Impl::clearFromHistory(History *history) {
 | 
				
			||||||
 | 
						for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.end();) {
 | 
				
			||||||
 | 
							if (i->peer == history->peer) {
 | 
				
			||||||
 | 
								i = _queuedNotifications.erase(i);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								++i;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto i = _notifications.find(history->peer->id);
 | 
						auto i = _notifications.find(history->peer->id);
 | 
				
			||||||
	if (i != _notifications.cend()) {
 | 
						if (i != _notifications.cend()) {
 | 
				
			||||||
		auto temp = createAndSwap(i.value());
 | 
							auto temp = createAndSwap(i.value());
 | 
				
			||||||
		_notifications.erase(i);
 | 
							_notifications.erase(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for_const (auto notification, temp) {
 | 
							for_const (auto notification, temp) {
 | 
				
			||||||
			_notificationsData.remove(notification);
 | 
								notification->close();
 | 
				
			||||||
			Libs::notify_notification_close(notification, nullptr);
 | 
					 | 
				
			||||||
			Libs::g_object_unref(Libs::g_object_cast(notification));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showNextNotification();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Manager::Impl::clearNotification(PeerId peerId, MsgId msgId) {
 | 
				
			||||||
 | 
						auto i = _notifications.find(peerId);
 | 
				
			||||||
 | 
						if (i != _notifications.cend()) {
 | 
				
			||||||
 | 
							i.value().remove(msgId);
 | 
				
			||||||
 | 
							if (i.value().isEmpty()) {
 | 
				
			||||||
 | 
								_notifications.erase(i);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showNextNotification();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Manager::Manager() : _impl(std_::make_unique<Impl>()) {
 | 
					Manager::Manager() : _impl(std_::make_unique<Impl>()) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Manager::clearNotification(PeerId peerId, MsgId msgId) {
 | 
				
			||||||
 | 
						_impl->clearNotification(peerId, msgId);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Manager::hasPoorSupport() const {
 | 
				
			||||||
 | 
						return _impl->hasPoorSupport();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Manager::hasActionsSupport() const {
 | 
				
			||||||
 | 
						return _impl->hasActionsSupport();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Manager::~Manager() = default;
 | 
					Manager::~Manager() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
 | 
					void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ class Manager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void start();
 | 
					void start();
 | 
				
			||||||
Manager *manager();
 | 
					Manager *manager();
 | 
				
			||||||
 | 
					bool supported();
 | 
				
			||||||
void finish();
 | 
					void finish();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void defaultNotificationShown(QWidget *widget) {
 | 
					inline void defaultNotificationShown(QWidget *widget) {
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,11 @@ inline void defaultNotificationShown(QWidget *widget) {
 | 
				
			||||||
class Manager : public Window::Notifications::NativeManager {
 | 
					class Manager : public Window::Notifications::NativeManager {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	Manager();
 | 
						Manager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void clearNotification(PeerId peerId, MsgId msgId);
 | 
				
			||||||
 | 
						bool hasPoorSupport() const;
 | 
				
			||||||
 | 
						bool hasActionsSupport() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	~Manager();
 | 
						~Manager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 | 
				
			||||||
#include "stdafx.h"
 | 
					#include "stdafx.h"
 | 
				
			||||||
#include "platform/win/main_window_win.h"
 | 
					#include "platform/win/main_window_win.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "platform/win/notifications_manager_win.h"
 | 
					#include "platform/platform_notifications_manager.h"
 | 
				
			||||||
#include "platform/win/windows_dlls.h"
 | 
					#include "platform/win/windows_dlls.h"
 | 
				
			||||||
#include "window/notifications_manager.h"
 | 
					#include "window/notifications_manager.h"
 | 
				
			||||||
#include "mainwindow.h"
 | 
					#include "mainwindow.h"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -321,7 +321,7 @@ void start() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Manager *manager() {
 | 
					Manager *manager() {
 | 
				
			||||||
	if (Global::WindowsNotifications()) {
 | 
						if (Global::NativeNotifications()) {
 | 
				
			||||||
		return ManagerInstance.data();
 | 
							return ManagerInstance.data();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nullptr;
 | 
						return nullptr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,11 +60,20 @@ void NotificationsWidget::createControls() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	addChildRow(_playSound, margin, lang(lng_settings_sound_notify), SLOT(onPlaySound()), Global::SoundNotify());
 | 
						addChildRow(_playSound, margin, lang(lng_settings_sound_notify), SLOT(onPlaySound()), Global::SoundNotify());
 | 
				
			||||||
	addChildRow(_includeMuted, margin, lang(lng_settings_include_muted), SLOT(onIncludeMuted()), Global::IncludeMuted());
 | 
						addChildRow(_includeMuted, margin, lang(lng_settings_include_muted), SLOT(onIncludeMuted()), Global::IncludeMuted());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QString nativeNotificationsLabel;
 | 
				
			||||||
#ifdef Q_OS_WIN
 | 
					#ifdef Q_OS_WIN
 | 
				
			||||||
	if (App::wnd()->psHasNativeNotifications()) {
 | 
						if (App::wnd()->psHasNativeNotifications()) {
 | 
				
			||||||
		addChildRow(_windowsNative, margin, lang(lng_settings_use_windows), SLOT(onWindowsNative()), Global::WindowsNotifications());
 | 
							nativeNotificationsLabel = lang(lng_settings_use_windows);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
 | 
				
			||||||
 | 
						if (App::wnd()->psHasNativeNotifications()) {
 | 
				
			||||||
 | 
							nativeNotificationsLabel = lang(lng_settings_use_native_notifications);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif // Q_OS_WIN
 | 
					#endif // Q_OS_WIN
 | 
				
			||||||
 | 
						if (!nativeNotificationsLabel.isEmpty()) {
 | 
				
			||||||
 | 
							addChildRow(_nativeNotifications, margin, nativeNotificationsLabel, SLOT(onNativeNotifications()), Global::NativeNotifications());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NotificationsWidget::onDesktopNotifications() {
 | 
					void NotificationsWidget::onDesktopNotifications() {
 | 
				
			||||||
| 
						 | 
					@ -132,13 +141,13 @@ void NotificationsWidget::viewParamUpdated() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NotificationsWidget::onWindowsNative() {
 | 
					void NotificationsWidget::onNativeNotifications() {
 | 
				
			||||||
	if (Global::WindowsNotifications() == _windowsNative->checked()) {
 | 
						if (Global::NativeNotifications() == _nativeNotifications->checked()) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Window::Notifications::manager()->clearAllFast();
 | 
						Window::Notifications::manager()->clearAllFast();
 | 
				
			||||||
	Global::SetWindowsNotifications(_windowsNative->checked());
 | 
						Global::SetNativeNotifications(_nativeNotifications->checked());
 | 
				
			||||||
	Local::writeUserSettings();
 | 
						Local::writeUserSettings();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ private slots:
 | 
				
			||||||
	void onDesktopNotifications();
 | 
						void onDesktopNotifications();
 | 
				
			||||||
	void onShowSenderName();
 | 
						void onShowSenderName();
 | 
				
			||||||
	void onShowMessagePreview();
 | 
						void onShowMessagePreview();
 | 
				
			||||||
	void onWindowsNative();
 | 
						void onNativeNotifications();
 | 
				
			||||||
	void onPlaySound();
 | 
						void onPlaySound();
 | 
				
			||||||
	void onIncludeMuted();
 | 
						void onIncludeMuted();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ private:
 | 
				
			||||||
	ChildWidget<Checkbox> _desktopNotifications = { nullptr };
 | 
						ChildWidget<Checkbox> _desktopNotifications = { nullptr };
 | 
				
			||||||
	ChildWidget<Ui::WidgetSlideWrap<Checkbox>> _showSenderName = { nullptr };
 | 
						ChildWidget<Ui::WidgetSlideWrap<Checkbox>> _showSenderName = { nullptr };
 | 
				
			||||||
	ChildWidget<Ui::WidgetSlideWrap<Checkbox>> _showMessagePreview = { nullptr };
 | 
						ChildWidget<Ui::WidgetSlideWrap<Checkbox>> _showMessagePreview = { nullptr };
 | 
				
			||||||
	ChildWidget<Checkbox> _windowsNative = { nullptr };
 | 
						ChildWidget<Checkbox> _nativeNotifications = { nullptr };
 | 
				
			||||||
	ChildWidget<Checkbox> _playSound = { nullptr };
 | 
						ChildWidget<Checkbox> _playSound = { nullptr };
 | 
				
			||||||
	ChildWidget<Checkbox> _includeMuted = { nullptr };
 | 
						ChildWidget<Checkbox> _includeMuted = { nullptr };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue